Difference between revisions of "Compile"
1>Admin |
m (1 revision imported) |
(No difference)
| |
Latest revision as of 10:36, 18 November 2022
| Compile (Системные функции) | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||
Функция производит компиляцию блока текста, заданного на внутреннем языке, и возвращает объект, представляющий результат компиляции. В зависимости от второго аргумента, блок может компилироваться в контексте текущей функции, глобальных модулей или без доступа к внешним переменным и функциям. Функция вызывает прерывание, если компиляция прервана из-за ошибки. Результирующий объект можно использовать многократно с функциями Exec и ExecEx, это быстрее, чем компилировать блок текста при каждом вызове. Блок текста может представлять собой набор произвольных инструкций и функций, а не одну функцию, т.е. блок текста может быть модулем.
Синтаксис
Compile(<Блок для компилирования (STRING)>,<Степень изолированности (INT)>=0,<Добавочные переменные (STRING)>,<Свойства исходного текста для отладчика (STRING,INT)>):<Компилированная функция в виде объекта (COMPILEDFUNCTION)>
Аргументы
<Блок для компилирования (STRING)>- Произвольный блок инструкций, может содержать имена функций, переменных, операции, магические функции, особые конструкции, в т.ч. объявления новых функций.<Степень изолированности (INT)>- (необязательный аргумент) Аргумент задает среду компиляции, и может принимать следующие значения:- 0 (по умолчанию) -- производить компиляцию в контексте текущей функции (в которой вызвана функция Compile). Это дает возможность использовать все переменные и все локальные функции текущей функции, а также глобальные переменные и функции.
- 1 -- производить компиляцию в контексте глобальных функций. Это дает возможность использовать в блоке текста только глобальные переменные и функции. Такой вариант изолированности предпочтительнее, если функция в дальнейшем будет экспортирована с помощью SaveFunctionToBuffer.
- 2 -- производить компиляцию без доступа к внешним функциям и переменным. Это полностью изолирует компилируемую функцию. Нужно, однако, понимать, что блок по-прежнему может косвенно вызывать внешние функции, являющиеся событиями, к примеру, с помощью функции Publish или подобных.
<Добавочные переменные (STRING)>- (необязательный аргумент) Аргумент задает имена переменных через запятую, которые компилятор будет считать доступными при начале компиляции (переменные должны быть также доступны позже в момент исполнения функции).<Свойства исходного текста для отладчика (STRING,INT)>- (необязательный аргумент) Аргумент указывает на исходный текст, который может быть использован в момент показа функции в отладчике (если она будет открыта в отладчике во время исполнения). Если аргумент не задан или равен нулю, исходный текст не будет доступен в отладчике, что может быть неудобным при отладке ошибок. Аргумент может принимать следующие значения:- Если аргумент число и равен 1, задает режим, когда исходный текст из первого аргумента привязывается к компилированной функции и будет выводиться в отладчике, как текст этой функции. Минусом этого режима является то, что текст останется в памяти до удаления объекта, что может потратить некоторый объем памяти.
- Если аргумент строка, он является путем и названием файла и указывает на исходный текст на диске (в формате sf), который будет загружен и показан в отладчике.
Возвращаемое значение
Возвращает новый объект компилированной функции, который можно исполнить с помощью функций Exec и ExecEx, либо экспортировать в память с помощью SaveFunctionToBuffer.
Примеры
//Пример из статьи ProfilerStart дополняется четвертым тестом с заранее компилированной функцией.
Function Square(a)
Exit a*a;
EndFunction
//Включить режим отладки
DebuggingRights(1);
//Очистить предыдущие результаты профилирования
ProfilerClear;
//Включить профайлер
ProfilerStart;
//Находим разницу во времени выполнения функции разными способами
For i:=1 to 100000 Do
Square(i);
EndDo;
For i:=1 to 100000 Do
ExecuteFunction("Square",1,i);
EndDo;
Стр:="Square(i);";
aFunc:=Compile(Стр);
For i:=1 to 100000 Do
Exec(aFunc);
EndDo;
//Останавливаем профайлер
ProfilerStop;
Период:=dbgHRPCCurrent();
For i:=1 to 100000 Do
Exec("Square(i)");
EndDo;
Период:=dbgHRPCGetPeriod(Период)/1000000;
Message("Выполнение Exec: "+Период+" мс.");
//Вызываем окно отладчика для просмотра результатов профилирования
DebugBreak;
//Функция DebugBreak не должна быть последней в модуле
Message("Тест выполнен успешно");
//Для i5 на Windows 7 результаты профилирования были следующими:
//* Прямой вызов функции занял 229 мс.
//* Использование функции ExecuteFunction заняло 307 мс.
//* Использование заранее скомпилированной функции заняло 357 мс.
//* Компиляция текста и вызов функции заняли 1181 мс.
// Комментарий: компиляция и выполнение уменьшает скорость работы профайлера, так как увеличивается количество исходных текстов в массиве, из которого производится поиск при профилировании
// Для массива текстов размером в ~10000, профайлер замедляет исполнение примерно в 1.4 раза по сравнению с работой профайлера с пустым массивом (коэффициент можно найти, если переставить местами
// циклы, включить цикл Exec в профилирование и сравнить результаты). Поэтому, время исполнения последнего цикла было найдено без помощи профайлера.
//Вывод: Для случая заранее скомпилированной функции скорость исполнения для этого примера выше в 3.3 раза по сравнению с компиляцией и исполнением.
// Для текстов с большим количеством быстро исполняемых инструкций, эта разница будет только возрастать.
// Скорость исполняемой заранее скомпилированной функции почти не уступает скорости обычного исполнения. См. также статью ProfilerStart