Compile

From SunFlurry wiki
Jump to: navigation, search
  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