Почему ASP часто компилирует мои представления?

У нас балансировка нагрузки на 4 сервера:

  • 4 ядра @2.6Ghz (E5-2650 v2)
  • ОЗУ объемом 14 ГБ
  • Windows 2012 R2
  • Высокая производительность.
  • IIS 8.5
  • ASP 5.3
  • EF 6.1

У каждого из них есть один пул приложений с одним рабочим процессом и одним веб-сайтом. На каждом сервере есть своя копия сайта (DLL и представления), работающая на локальном диске. Мы используем виртуальные каталоги IIS, чтобы указывать на общие ресурсы на кластерном файловом сервере для файлов журналов и общих изображений и т.д. (Только для контента). Пулы приложений устанавливаются так, чтобы они не выключались в режиме ожидания (интервал 0), и мы также отключили интервал перезаписи каждые 1740 минут.

У нас установлен новый агент Relic.NET на всех серверах, и, просматривая наш медленный журнал транзакций, я вижу, что многие запросы занимают 15 секунд или около того. Посмотрев в след, я вижу общий вызов System.Web.Compilation.AssemblyBuilder.Compile() и System.Web.Compilation.BuildManager.CompileWebFile().

Насколько я знаю или понимаю, ASP будет компилировать эти представления при первом запросе к ним и кэшировать его (во временные файлы ASP в C:\Windows\Microsoft.Net), а затем загружать оттуда для последующих запросов.

Я смущен, как это происходит так часто - когда я посещаю эти URL-адреса, TTFB составляет около 400 мс, и из-за постоянной нагрузки я не вижу, как веб-сайты "теряют" свой кеш и нуждаются в компиляции просмотров снова, Эти страницы часто попадают - это магазин электронной коммерции, и я вижу, что это происходит часто, и на наших самых популярных страницах: каталог (категория/бренд/пол и т.д.) Списки и сведения о продукте.

Я установил параметры для каждого пула приложений для регистрации события при повторной обработке, и не было событий, зарегистрированных при проверке службы WAS в средстве просмотра событий. У нас также установлен новый сервер Relic, и, просматривая данные за последние 6 часов, я не вижу никакого падения в использовании ОЗУ на любом из серверов, что указывает на повторную загрузку пула приложений. Это действительно озадачило меня!

Я собираюсь перейти к предварительной компиляции наших представлений как части нашего процесса выпуска - это действительно имеет смысл. Но похоже, что это работает или маскирует проблему, которая, насколько я вижу, не должна происходить. Мы создаем наш сайт в режиме выпуска и <compilation debug="false" /> на всех web.config файлах.

Может ли кто-нибудь подумать о каких-либо причинах этого?

Ответ 1

Это из-за того, как компиляция JIT (Just-In-Time) работает.

Когда вы создаете приложение, оно преобразуется в .NET Intermediate Language (MSIL) или промежуточный язык (IL).

Как только ваши приложения будут доступны, Common Language Runtime (CLR) преобразует только выполненные IL-части вашего кода в собственные инструкции.

Процесс компиляции Just-In-Time преобразует IL в собственные машинные команды и является частью CLR.

В упрощенном виде, когда вы запускаете приложение .NET, и ваша программа вызывает метод. Компилятор JIT считывает IL из метаданных и компилирует его в собственные инструкции и запускает его. Затем, когда ваша программа вызывает тот же метод, CLR выполняет непосредственно инструкции CPU. Этот процесс добавляет некоторые накладные расходы для первого вызова метода. Вы можете пойти с другим вариантом предварительной компиляции вашего приложения с помощью NGEN, что обычно не рекомендуется, потому что вы потеряете некоторые оптимизации, которые может выполнять только JIT из-за его осведомленности о базовой аппаратной платформе. Эти две статьи имеют более подробную информацию http://geekswithblogs.net/ilich/archive/2013/07/09/.net-compilation-part-1.-just-in-time-compiler.aspx и https://msdn.microsoft.com/en-us/library/ms366723.aspx

Есть и другие вещи, которые вы можете попробовать, которые могут помочь вам ускорить ваше приложение. Вы можете использовать модуль прогрева приложения IIS Как разогревать приложение ASP.NET MVC на IIS 7.5?, реализовать распределенное кэширование и т.д., Чтобы облегчить некоторые узкие места вашего приложения.