Пакетна компіляція в ASP.NET (вихідні коди)

Напевно багато хто помічав, що перше звернення до ASPX сторінці займає значно більше часу, ніж наступні і при цьому помітно підвищене споживання ресурсів Веб-сервера. Це ASP.NET виробляє т.зв. динамічну компіляцію або компіляцію "на-льоту" (on-the-fly). Вона відбувається автоматично, коли браузер запитує сторінку з сервера. Очевидно, що хотілося б мати засіб уникнути подібних затримок. Далі я розгляну, що ж пропонує ASP.NET для боротьби з цим, а так само наведу деякі деталі того, як відбувається обробка запитів до сторінок з точки зору динамічної компіляції.

Трохи теорії


Як відомо, ASP.NET на відміну від ASP виробляє компіляцію (а не інтерпретацію) ASPX сторінок. При такій компіляції для кожної сторінки або групи сторінок створюється збірка (assembly) – динамічна бібліотека dll.

Зауважу, що мова йде саме про сторінки ASPX і серверних скриптах всередині цих сторінок, а не про т.зв. code behind файлах, які повинні бути заздалегідь скомпільовані та розміщені в папці BIN або глобальному кеші збірок (GAC – Global Assembly Cache). Використання code behind файлів є кращим способом, тому що дозволяє домогтися поділу коду та подання. На жаль це не виключає компіляції ASPX сторінок.

Збірка містить MSIL (MicroSoft Intermediate Language) код, який в свою чергу перед фактичним виконанням компілюється у виконуваний код. Одиниця компіляції – викликаний метод. Це т.зв. JIT-компіляція. Соственно кажучи, цим вже займається не ASP.NET, а.NET Framework, так як з точки зору Framework скомпільована ASPX сторінка – це звичайне складання, що містить кілька класів, що підтримують певні інтерфейси.

Після JIT-компіляції виконуваний код методу кешируєтся і подальші звернення до цього методу відбуваються безпосередньо.

Таким чином є дві області, в яких відбуваються затримки при зверненні до ASPX сторінці:


Останню ми розглядати не будемо, а от у процес компіляції "на-льоту" можна втрутитися.

Перший запит сторінки


ASP.NET визначає, що потрібно компіляція сторінки, у випадку, якщо для неї немає збереженої складання або сторінка була змінена. Далі виробляються дві основні операції:


Якщо сторінка вже була раніше скомпільована, тобто для неї є відповідна збірка, то дана збірка використовується в якості обробника запитаної сторінки.

Давайте уявимо собі реальну ситуацію, коли Веб-сайт містить кілька сотень або тисяч сторінок. Що відбувається, коли користувач запитує сторінку з сервера? Правильно – компіляція цієї сторінки. Тепер уявіть, що сайт навантажений. Очевидно, що в цьому випадку час відгуку сервера зростає, а це не є добре. До речі – це стосується і Веб-сервісів, але це трохи інша історія, так як тут втручаються механізми Reflection і серіалізациі.

Що ж можна зробити, щоб оптимізувати процес динамічної компіляції?

ASP.NET пропонує засіб, зване "пакетна компіляція" (batch compilation).

Пакетна компіляція


За процес компіляції відповідає елемент конфігурації <compilation> файлу web.config:


<configuration>
<system.web>
<compilation>
<compilation debug=”true/false”
batch=”true/false”
batchTimeout = "число секунд"
defaultLanguage = "мова"
maxBatchSize = "Максимальна кількість сторінок на пакетну компіляцію"
maxBatchGeneratedFileSize = "максимальний розмір
згенерованого вихідного файлу в KB "
tempDirectory = "директорія для тимчасових файлів при компіляції">
</compilation>



















































Атрибут  Значення  Опис 
Debug    Компіляція з налагоджувальною інформацією. За замовчуванням false 
  true  Компіляція з налагоджувальною інформацією. Зберігаються вихідні файли мовою, зазначеною в атрибуті defaultLanguage.
Зауваження: при включеній налагоджувальної інформації пакетна компіляція не проводиться 
  false  Компіляція без налагоджувальної інформації.
defaultLanguage    Мова, в який розбирається сторінка. За замовчуванням vb, але Visual Studio.NET встановлює його в c #
batch    Пакетна компіляція
  true  Пакетна компіляція включена
  false  Пакетна компіляція вимкнена
batchTimeout    Вказує тайм-аут, у секундах, для пакетної компіляції. Якщо компіляція не може бути виконана за цей період, то компілятор повертається до стандартного режиму компіляції для поточної сторінки
maxBatchGeneratedFileSize    Максимальний розмір згенерованого вихідного файлу в KB
maxBatchFileSize    Максимальна кількість сторінок на одну пакетну компіляцію
tempDirectory    Директорія для тимчасових файлів при компіляції

Щоб включити цю опцію, треба встановити атрибут batch рівним true, а debug рівним false.


Що ж станеться в цьому випадку? При запиті будь-якої сторінки з каталогу, ASP.NET скомпілюйте всі сторінки і створить одну збірку. Тобто замість безлічі невеликих dll (одна dll для однієї сторінки) вийде одна велика dll для всіх сторінок в цьому каталозі.

Тут треба зауважити, що пакетна компіляція проводиться на основі каталогу, а не для всього Веб-додатки.

Очевидно перевага такого підходу – не треба компілювати і розбирати сторінку за сторінкою при першому зверненні до них. Але як то кажуть, безкоштовний сир буває тільки в мишоловках. І даний підхід – не виняток. Негативна сторона полягає в тому, що така компіляція займає більше ресурсів сервера і може збільшити час відгуку сторінок, що беруть участь в такій компіляції. Але на це є своє протиотрута – "перед-пакетна" компіляція (pre-batch compilation). Тобто перед тим, як хто-небудь запросить будь-яку сторінку з сервера, Ви самі звертаєтеся до будь-якій сторінці, тим самим ініціюючи процес пакетної компіляції і примушуючи ASP.NET створити і закеширувати всі сторінки сайту. Звідси мораль – завжди перед передачею Веб-додатки в "виробництво" запитуйте сторінки з усіх віртуальних каталогів.


Технічні деталі


Тепер трохи про технічні деталі. Будь-яка сторінка ASPX при зверненні до неї автоматично компілюється і потрапляє в:

% Systemroot% / Microsoft.NET / Framework / <версія> / Temporary ASP.NET Files / <сайт> / nnnnn / mmmm

(Nnnnn і mmmm – випадкові послідовності).

Частина шляху "% systemroot% / Microsoft.NET / Framework / <версія> / Temporary ASP.NET Files" може бути змінена за допомогою атрибуту tempDirectory

На моєму комп'ютері – це:

C: WINDOWSMicrosoft.NETFrameworkv1.1.4322Temporary ASP.NET FilesTestProject 5afd0e9e951ffc7

У залежності від значення атрибута batch, Там буде знаходитися один або більше файлів виду aabbcc.dll, а так само налаштування для зв'язування (Test.aspx.mmmmm.xml).

Хитрість полягає в тому, що у випадку з batch=true, Там буде всього одна dll, але в налаштуваннях зв'язування (нагадую – це файли виду Test.aspx.mmmmm.xml) буде вказана одна і та ж dll для всіх сторінок. Назва dll вибирається випадковим чином, аналогічно вибору імені тимчасового файлу.

Також ця директорія (а точніше піддиректорії assembly) використовується для т.зв. "Тіньового" копіювання використовуваних у Веб-додатку dll, що дозволяє ASP.NET не блокувати їх (згадайте ASP і COM).

Що відбувається, якщо змінюється одна сторінка


А тепер – найцікавіше. Ви включили batch=true, Виробили предкомпіляцію і насолоджуєтеся швидкою роботою сайту. У цей момент виявляється, що необхідно виправити одну сторінку, скажімо Test.aspx. Що відбувається при наступному запиті цієї сторінки ?

ASP.NET компілює її і створює окрему збірку з випадковим ім'ям, наприклад xxyyzz.dll. Потім змінюється настройка зв'язування, так що тепер ASP.NET знає: "код виконання сторінки Test.aspx знаходиться не в aabbcc.dll, а в xxyyzz.dll ". При цьому в старій збірці залишається код для сторінки Test.aspx, але він не використовується.

Як влаштована сторінка або магія в дії


Якщо зазирнути в xxyyzz.dll за допомогою утиліти ildasm (Входить до складу. NET Framework SDK; також встановлюється з Visual Studio.NET), то можна переконатися, що в ній знаходиться клас Test_aspx, який успадкований від того класу, який ви використовували в якості code behind (Test.aspx.cs, якщо такий був, що не є обов'язковим; це клас, про який директива @ Page на початку Вашої сторінці повідомляє: Codebehind = "Test.aspx.cs" Inherits = "TestProject.Test"), який у свою чергу успадкований від System.Web.UI.Page – Базовий обробник ASPX сторінок (тобто клас, що підтримує інтерфейс IHttpHandler і що у конвеєрі запитів IIS / ASP.NET).

Для кращого розуміння процесу треба встановити debug=true.

Зауважу, що при цьому перестане працювати пакетна компіляція, але це дає нам можливість побачити, як наша сторінка виглядає в C #.

Тим, хто не збирається займатися подібними дослідженнями можу повідомити, що в основному там наступне:


Якщо запустити Task Manager, то можна помітити, як процес csc.exe з'являється і зникає. Це запускається компілятор C #, який власне і робить компіляцію вихідного файлу, отриманого в результаті розбору сторінки.

Після чого ця збірка використовується конвеєром ASP.NET для обробки запиту на ресурс Test.aspx.

Висновок


Незважаючи на те, що при програмуванні ASP.NET не потрібне знання роботи середовища виконання, але в реальних проектах часто потрібна тонка настройка Веб-сервера, особливо під навантаженням. Сподіваюся, що інформація в даній статті допоможе розробникам краще зрозуміти роботу ASP.NET і, можливо, вирішити деякі проблеми, зокрема, з помилками з прав доступу, кешуванням компонентів і т.п.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*