Кэширование результатов обращения к функции |
Для повышения быстродействия приложения можно кэшировать результаты обращения к функции. При повторном обращении к кэшированной функции с теми же параметрами вычисления не производятся, а используется ранее вычисленный результат.
Кешировать имеет смысл функции, результат выполнения которых (в т.ч. значения var-параметров на выходе) зависит только от параметров, и на выполнение которых не влияет состояние системы.
Кэшироваться может только функция, параметры которой являются простыми типами. В противном случае выдаётся ошибка компиляции. По умолчанию кэшируются все её var-параметры и результат, а зависимость устанавливается от всех остальных параметров.
Для любого параметра умолчания можно изменить задав атрибут кэширования сразу после типа в квадратных скобках.
Для кэширования используется механизм "кэширования таблицами в памяти". Таким образом для настройки кэширования используются те же конфигурационные параметры, что и для БД: DataBase.CacheSize, CacheTables, CacheTime, CacheProtocol.
Параметры конфигурации БД описаны в документе "Средство разработки
. Параметры конфигурации системы".Идентификатором кэша результатов функций является слово $$ZERO. Таким образом для этого кэша можно задать группу приоритетов и время актуальности данных этого кэша через его группу приоритетов.
Необходимо иметь в виду, что если интерфейс кэшируемый, то cmOnVipUnload и вызова прикладного деструктора не освобождает его, а помещает в кэш. При этом все поля остаются проинициализированными, в т.ч. поля со ссылками.
после посылкиПоскольку все ссылки остаются живыми, то объекты, на которые они ссылаются, сразу не освобождаются. А освобождаются позже, при выходе из приложения при освобождении всех объектов, находящихся в кэше. Однако при выходе из приложения блокируется работа интерпретатора, поэтому прикладной код не вызывается. Для освобождённых интерфейсов это не страшно, поскольку для них соответствующий прикладной код (деструктор) был вызван ранее, при помещении в кэш. Но для тех объектов, на которые они ссылаются, это может быть критично.
Поэтому для корректной работы следует в кэшируемых интерфейсах обрабатывать cmOnVipUnload и /или cmDone (в зависимости от предполагаемой схемы использования), и в обработке вручную занулять ссылки на используемые интерфейсы - даже если эти ссылки автоматические.
Например, в примере 3 при нажатии на кнопку 1 и выходе из приложения сообщения о выгрузке Aaa и Zzz не приходят.
Если же интерфейс BbbTest сделать некэшируемым, то придёт сообщение о выгрузке Aaa. Сообщение о выгрузке Zzz не придёт, поскольку на Zzz ссылается Aaa. Интерфейс Ааа кэшируемый и после выгрузки не уничтожается, а помещается в кэш. В результате у него остаётся неосвобожденная ссылка на Zzz. Эта ссылка освобождается при освобождении закэшированных объектов при выходе из приложения, когда интерпретатор уже заблокирован.
Для управления кэшированием в vip добавлены функции:
Пример 1.
Кэшируется с и результат функции, зависимость установлена от а и b:
function f1 (a: word; b: longint; var c: string) : boolean; cacheable;
Пример 2.
Кэшируется результат функции, зависимость установлена от a и c:
function f2 (a: word; b: longint [nocacheinfl]; var c: string [cacheinfl, nocached] ) : boolean; cacheable;
Пример 3.
Освобождение ссылок в кэшируемых интерфейсах.
//========================================================= objInterface objAaa; procedure p; procedure p2; end; vipInterface Aaa implements objAaa licensed(free); //========================================================= objInterface objZzz; procedure p; procedure p2; end; vipInterface Zzz implements objZzz licensed(free); //========================================================= interface Aaa cacheable; var z: Zzz; //--------------------------------------------------------- public procedure p; { Message(' Aaa.p!'); } //--------------------------------------------------------- public procedure p2; { z.p; } //--------------------------------------------------------- handleEvent cmOnVipload: Message('Load Aaa'); cmOnVipUnload: Message('Unload Aaa'); end; end. //========================================================= interface Zzz cacheable; var a: Aaa; //--------------------------------------------------------- public procedure p; { Message(' Zzz.p!'); } //--------------------------------------------------------- public procedure p2; { a.p; } //--------------------------------------------------------- handleEvent cmOnVipload: Message('Load Zzz'); cmOnVipUnload: Message('Unload Zzz'); end; end. //========================================================= interface BbbTest cacheable; //--------------------------------------------------------- create view from x$files ; var a: Aaa; var z: Zzz; //--------------------------------------------------------- screen sc1 ('Пример вызова кэшируемых интерфейсов.'); table x$files; buttons cmButton; cmCancel; << <. Кнопка 1 .> <. Отменить .> >> end; //--------------------------------------------------------- handleEvent cmButton: a.p2; end; end.
"Описание функции и процедуры. "
Кэширование результатов обращения к функции доступно начиная с Атлантис 5.1.36.