Первый запрос медленный при импорте представлений Razor из библиотеки классов в ASP.NET Core 2.1 - PullRequest
0 голосов
/ 04 октября 2019

В ASP.NET Core 2.1 у меня есть проект DLL ( Microsoft.NET.Sdk ) с представлениями Razor для совместного использования общих частичных представлений, таких как навигация, нижний колонтитул, ..., с несколькими приложениями. Он был создан как описанный здесь . Итак, у меня есть приложение ASP.NET Core 2.1 MVC, которое включает в себя эти библиотеки и встраивает частичные представления.

Хотя это работает, я заметил значительное увеличение времени загрузки первой страницы в этом приложении. На основной HTML-документ ушло около 3 секунд. Последующие запросы выполняются довольно быстро (~ 30-40 мс). Я попытался удалить все частичное представление в приложении, которое было встроено в общую DLL. Теперь первый запрос намного быстрее (около 300 мс).

Так что, похоже, это вызвано загрузкой Razor-представлений из общего проекта DLL. Я пытался предварительно загрузить сборку, используя различные методы, подобные этому, в методе AppStartup (вдохновленный этим вопросом ):

GC.KeepAlive(typeof(Assets.AssetStartup));
System.Reflection.Assembly.Load("Assets"); 

Нет большой разницы в производительности, все равно потребовалось ~ 2,9 секундыпервый запрос.

Как я могу улучшить это?

Я знаю о прогреве от EntityFramework, поэтому у меня возникла идея решить эту проблему аналогичным образом. Но я не уверен, где именно это замедляет работу моего приложения: загружается ли сборка (и мои попытки предварительной выборки были в некотором роде ошибочными), или это все еще связано с компиляцией Razor?

Потому чтоЯ также знаю об улучшениях производительности, предварительно скомпилировав представления Razor. В ASP.NET Core 1 я включил это вручную, и первый запрос был заметно быстрее. Так как Microsoft переписала эту часть и включила предварительную компиляцию по умолчанию, но мое приложение DLL Razor не создает файл с именем {AppName}.Views.dll (где они есть в приложениях MVC), я не уверен, что это может быть проблемой.

1 Ответ

0 голосов
/ 04 октября 2019

Некоторые сообщения , а также сообщения в блоге указывают на наличие проблем с предварительной компиляцией в проектах Razor lib. Но я вспомнил из документации .NET Core , что MvcRazorCompileOnPublish устарела и удалена в 3.0. Это отключает новый Razor SDK. Это кажется не надежным решением для меня.

Итак, я создал пустой проект Razor и сравнил файл csproj с моим проектом lib. Он показывает, что он ссылается на Microsoft.NET.Sdk.Razor вместо Microsoft.NET.Sdk из моего проекта (созданного как ядро ​​.NET базовая библиотека классов ядра .NET). После изменения SDK моя папка Debug также содержит файл Assets.Views.dll, который указывает на предварительную компиляцию.

Он также добавлен NuGet, что можно легко проверить, открыв файл .nupkg с помощью 7zip. Папка lib/netcoreapp2.1 теперь также содержит .Views.dll.

Это решение увеличивает время обработки первого запроса с ~ 3 секунд до 1,1 секунды. Намного быстрее, но все же намного медленнее по сравнению с 300 мс без внешней DLL. Я рассматриваю это как часть решения, но, похоже, существуют дополнительные узкие места, которые замедляют первый запрос. Я открыт для дополнительных идей, как улучшить эту последнюю задержку.

В настоящее время я включаю только четыре частичных представления из Razor DLL. Один из них имеет 108 строк HTML-кода с небольшим количеством динамической логики и два встроенных сервиса. Другие намного меньше и еще не содержат много динамической логики. Я также старался не включать в себя более частичное представление, без заметной разницы.

Не могу поверить, что включение четырех относительно небольших частичных представлений из внешней библиотеки Razor задерживает первый запрос на 800 мс. Это не тот случай, когда представление находится локально в одном проекте.

Предварительная загрузка не является проблемой

Найдена запись в блоге Рика Штрола с фрагментом, в котором перечислены все загруженные сборки:

var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies) {
    Console.WriteLine(assembly.GetName());
}

Я запустил это в ConfigureService моего приложения, которое использует Razor DLL. Он показывает обе сборки из моего DLL-файла Razor (Assets и Assets.Views). Я думаю, что это так, потому что я извлекаю информацию о сборке, чтобы передать ее как EmbeddedFileProvider в RazorViewEngineOptions. Однако это объясняет, почему мои попытки предварительной загрузки никак не влияют на время генерации страницы.

...