Внутреннее устройство локального кэша сборок Fore\Fore.NET

Наверное, каждый разработчик, использовавший в своей профессиональной деятельности языки программирования Fore и Fore.NET, сталкивался с механизмом локального кэширования Fore\Fore.NET сборок. Понимание основ работы данного механизма может сильно повлиять на эффективность и быстродействие разрабатываемых прикладных систем, использующих Fore\Fore.NET. В этой статье будет подробно описано внутреннее устройство локального кэша сборок, а также особенностей, которые стоит учитывать при разработке.

Fore – это объектно-ориентированный язык программирования, основанный на технологии Microsoft Component Object Model (COM). Его основным преимуществом для нас является глубокая интеграция в Prognoz Platform. Например, с его помощью вы можете создавать обработчики событий регламентных отчетов, выражения для вычислимых фактов кубов, вычислимые поля в таблицах, а также полноценные прикладные системы.

Fore.NET – это относительно молодой преемник Fore (появился в 2008 году). Основная цель его создания — возможность интеграции прикладных решений и систем с Microsoft .NET Framework. Например, с его помощью вы можете реализовать интерфейс вашей системы на Windows Forms или WPF или использовать WCF для интеграции с существующими веб-сервисами.

В статье вы найдете подробное описание внутреннего устройства и особенностей реализации локального кэша Fore\Fore.NET сборок. Однако, стоит отметить, что вся приведенная здесь информация представляет собой описание внутренней реализации, которая может быть изменена в будущем.

Описание локального кэша сборок

Локальный кэш сборок представляет собой иерархическую структуру каталогов, в которых хранятся скомпилированные Fore\Fore.NET сборки и их метаданные. Использование механизма локального кэширования позволяет значительно ускорить процесс работы с Fore и Fore.NET за счет избегания лишних операций компиляции и минимизации обращений к БД.

Расположение локального кэша сборок

Локальный кэш сборок может быть расположен в одном из перечисленных каталогов.

1. Локальный профиль текущего пользователя Windows, полный путь до каталога которого указан в переменной окружения %LOCALAPPDATA% (например, C:\Users\username\AppData\Local\, где username – это имя текущего пользователя Windows)

2. Пути, указанные в переменной окружения %TMP%

3. Пути, указанные в переменной окружения %TEMP%

4. Путь, указанный в переменной окружения %USERPROFILE%

5. Системный каталог для временных файлов (обычно C:\Windows\Temp)

Во время подключения к репозиторию выполняется их последовательная проверка: в случае, если текущий пользователь Windows, использующий Prognoz Platform, обладает правами на запись в каталоге, локальный кэш сборок будет расположен именно в нем. Если нет, выполняется проверка следующего каталога. Если все каталоги, перечисленные ниже, имеют защиту от записи, при использовании локального кэша (например, при попытке компиляции или выполнения Fore.NET сборки) возникнет исключительная ситуация. Стоит отметить, что, начиная с Prognoz Platform версии 8.0, появилась возможность явного задания каталога, в котором будет расположен локальный кэш сборок. Для этого необходимо в ветке реестра, соответствующей используемой мажорной версии Prognoz Platform (например, HKEY_CURRENT_USER\Software\JSC Prognoz\Prognoz\8.0), создать строковое значение с именем CachefilePath. Оно содержит абсолютный путь до каталога, в котором должен быть размещен кэш сборок.

В случае когда значение в реестре есть, при подключении к репозиторию первой будет осуществлена проверка именно этого пути. И если есть права на запись в этом каталоге, локальный кэш будет размещен именно в нем. В противном случае, будет выполнен поиск каталога в соответствии с вышеописанным алгоритмом.

Структура локального кэша сборок

Каталоги AsmCache

Локальный кэш сборок имеет иерархическую структуру, которая схематично изображена на рис. 1.

Каталоги AsmCacheN (AsmCache0, AsmCache1, …) соответствуют одновременно запущенным экземплярам Prognoz Platform. Так, например, если одновременно запущены два экземпляра Prognoz Platform (например, два процесса Studio.exe), то в локальном кэше будет как минимум два каталога AsmCache. Их может быть и больше, если раньше были одновременно запущены более двух экземпляров Prognoz Platform.

При работе с Fore\Fore.NET в нескольких одновременно запущенных экземплярах Prognoz Platform стоит учитывать, что каждый из этих экземпляров будет использовать свой собственный каталог для локального кэширования. Рассмотрим следующий сценарий (для простоты будем считать, что изначально локальный кэш сборок был пуст):

1. Пользователь запускает один экземпляр Prognoz Platform (экземпляр A) — это приводит к созданию пустого каталога AsmCache0.

2. Затем пользователь запускает другой экземпляр Prognoz Platform (экземпляр Б) и выполняет запуск или компиляцию Fore\Fore.NET сборок, кэширование которых при этом выполняется в каталоге AsmCache1.

3. Пользователь закрывает экземпляр Б и пытается выполнить в экземпляре А ранее скомпилированную сборку, находящуюся в каталоге AsmCache Однако, поскольку экземпляр A по-прежнему использует каталог AsmCache0, при обращении к сборке может быть выполнена ее повторная компиляция.

Однако в большинстве случаев повторной компиляции удастся избежать за счет кэширования скомпилированных сборок в БД – в этом случае скомпилированные сборки будут скопированы из БД на жесткий диск.

Возможность кэширования Fore\Fore.NET сборок в БД задается в параметрах репозитория. Для того чтобы убедиться, что данная опция включена, необходимо открыть диалог настроек репозитория, изображенный на рис. 2, и проверить, чтобы элемент управления «Кэширование сборок только на локальном диске» был неактивен.

Возможность кэширования Fore\Fore.NET сборок в БД является незаменимой при разворачивании масштабных прикладных систем, т.к. позволяет значительно уменьшить время первого запуска за счет избегания необходимости компиляции, которая в общем случае может занять достаточно длительное время.

Однако на локальных компьютерах разработчиков возможность кэширования сборок в БД обычно отключена, т.к. при ней с каждой компиляцией будет производиться обновление сборки в БД. Использование только локального кэширования в этом случае позволяет минимизировать число обращений к БД и сетевой трафик.

Стоит отметить, что возможность кэширования Fore.NET присутствует только в версии Prognoz Platform 8.0. В версиях Prognoz Platform 7.x выполнение описанных выше действий приведет к повторной компиляции.

Каталог Mod

Как следует из рис. 1, каждый каталог AsmCacheN также имеет иерархическую структуру: внутри находится каталог Mod, который в свою очередь содержит каталоги, соответствующие используемым репозиториям («PROGNOZPLATFORM7», «PROGNOZPLATFORM8»).

Каждый из каталогов, соответствующий конкретному репозиторию, содержит каталоги, предназначенные для хранения сборок определенной версии Prognoz Platform (версия указывается в формате Major.Minor.Revision).

Каталоги Compile и Runtime

Правила хранения Fore и Fore.NET сборок в локальном кэше довольно сильно различаются.

Скомпилированные Fore сборки размещаются в каталоге Runtime. Формат имени Fore сборок, находящихся в кэше, представлен на рис. 3.

где Id – идентификатор Fore сборки.

Стоит отметить, что формат внутреннего содержимого *.yad файлов не документирован и является бинарным представлением Fore сборки.

Перейдем к рассмотрению правил, описывающих хранение Fore.NET сборок. Fore.NET сборки, в отличие от Fore сборок, хранятся в двух различных каталогах: Compile и Runtime:

  • в каталоге Compile хранится последняя версия скомпилированных Fore.NET сборок;
  • в каталоге Runtime хранятся Fore.NET сборки, запущенные на выполнение.

Основная причина такого разделения заключается во внутреннем ограничении платформы .NET отсутствии возможности выгрузки отдельных сборок из адресного пространства процесса. Возможность выгрузки доменов приложения (AppDomain) имеет ряд ограничений и в настоящее время не может быть использована.

Формат имени Fore.NET сборки представлен на рис. 4.

где

  • Id – идентификатор Fore.NET сборки;
  • Key – ключ Fore.NET сборки;
  • Version – версия NET сборки.

Под версией сборки понимается следующее. При первой компиляции каждая сборка имеет версию 1. В случае, если исходный код сборки был изменен при попытке ее запуска (или компиляции), версия сборки будет увеличена на единицу. Причина введения подобного механизма версионности заключается в описанном выше ограничении .NET Framework, не позволяющим выгружать отдельные сборки из адресного пространства процесса.

В связи с этим необходимо отметить, что при использовании Fore.NET стоит обращать особое внимание на число Fore.NET сборок в локальном кэше. Наличие большого числа «одинаковых» сборок (т.е. сборок, идентификатор и ключ которых совпадает) с различной версией может быть признаком ошибки в прикладной системе. Например, использование метода IMetabaseCache.FlushAll для очистки кэша объектов репозитория приводит к очистке метаданных локального кэша сборок, что, в свою очередь, приводит к повторной компиляции. При этом выполнение повторной компиляции будет влиять не только на время отклика системы, но также и на число используемой оперативной памяти и на количество используемого дискового пространства, поскольку вновь скомпилированная сборка будет загружена в адресное пространство процесса и помещена в локальный кэш сборок.

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

В каталоге Runtime также можно увидеть каталоги, имеющие имя вида DN (D1, D2, …). Такие каталоги используются отладчиком Fore.NET, и в них находятся сборки, скомпилированные с отладочной информацией.

Читайте также

Комментарии

Подробнее о политике использования персональных данных