Многие нативные функции предназначены для того, чего нельзя или очень сложно сделать другими средствами.
Лишь некоторые нативные функции можно заменить эквивалентным кодом на Pawn - обычно это функции для работы с целыми числами и строковые функции.
Рассмотрим это на примере двух алгоритмов преобразования всех символов верхнего регистра в строке на символы нижнего регистра.
В одном алгоритме для преобразования будет использоваться функция tolower, а в другом - аналогичный код на Pawn.
Для сравнения скорости выполнения каждого из алгоритмов воспользуемся профайлером.
/*======== Настройки =========================================================*/
// Кол-во итераций в циклах.
const PROFILER_ITERATIONS_MAJOR = 10_000;
const PROFILER_ITERATIONS_MINOR = 100;
// Названия отрывков кода.
new const code_snippets_names[2][] =
{
{"native function"},
{"Pawn function"}
};
#include <core>
LowerCase0(string[])
{
static pos;
for (pos = -1; string[++pos] != '\0';)
string
[pos
] = tolower(string
[pos
]);}
LowerCase1(string[])
{
static pos, c;
for (pos = 0; ; ++pos)
{
if (0 != (c = string[pos]))
{
if (c < 'A')
continue;
if ('Z' < c)
continue;
string[pos] = c + ('a' - 'A');
continue;
}
break;
}
}
#define Prerequisites();\
static string[] = "ABCabcAABBCCaabbccXYZxyzXXYYZZxxyyzz";
#define CodeSnippet0();\
LowerCase0(string);
#define CodeSnippet1();\
LowerCase1(string);
/*======== Конец настроек ====================================================*/
Результаты:
Код:
Тестирование: <native function> vs <Pawn function>
Режим: интерпретируемый, 10000x100 итераций.
native function: 8001
Pawn function: 2263
Код:
Тестирование: <native function> vs <Pawn function>
Режим: с JIT-компиляцией, 10000x100 итераций.
native function: 5072
Pawn function: 213
Ещё пример: определить из двух чисел то, которое больше.
Для таких целей в Pawn есть нативная функция max, но можно сделать и свой код.
/*======== Настройки =========================================================*/
// Кол-во итераций в циклах.
const PROFILER_ITERATIONS_MAJOR = 100_000;
const PROFILER_ITERATIONS_MINOR = 1000;
// Названия отрывков кода.
new const code_snippets_names[2][] =
{
{"native function"},
{"Pawn function"}
};
#include <core>
new max_value;
#pragma unused max_value
#define Prerequisites();\
new a = random(100), b = random(100);
#define CodeSnippet0();\
max_value = max(a, b);
#define CodeSnippet1();\
max_value = (b > a) ? b : a;
/*======== Конец настроек ====================================================*/
Результаты:
Код:
Тестирование: <native function> vs <Pawn function>
Режим: интерпретируемый, 100000x1000 итераций.
native function: 4564
Pawn function: 3794
Код:
Тестирование: <native function> vs <Pawn function>
Режим: с JIT-компиляцией, 100000x1000 итераций.
native function: 3010
Pawn function: 353
В обоих приведённых выше примерах реализация на Pawn обходит по производительности нативные функции, причём с JIT преимущество кода на Pawn только увеличивается.
Но бывают и случаи, когда код на Pawn работает быстрее нативной функции только при использовании JIT-компиляции.
Рассмотрим ещё один пример: удалить из строки все пробелы.
/*======== Настройки =========================================================*/
// Кол-во итераций в циклах.
const PROFILER_ITERATIONS_MAJOR = 10_000;
const PROFILER_ITERATIONS_MINOR = 100;
// Названия отрывков кода.
new const code_snippets_names[2][] =
{
{"native function"},
{"Pawn function"}
};
#include <string>
RemoveSpaces0(string[])
{
static pos;
pos = 0;
while (strfind(string
, " ", false, pos
) != -1) }
RemoveSpaces1(string[])
{
static pos, pos2, c;
for (pos = 0, pos2 = 0;; ++pos)
{
switch (c = string[pos])
{
case ' ': continue;
case '\0':
{
string[pos2] = '\0';
return;
}
}
string[pos2++] = c;
}
}
#define Prerequisites();\
static string[] =\
" AaBbCcDdEeFfGgHh IiJjKkLlMmNnOoPp QqRrSsTtUuVvWwXx YyZz ";
#define CodeSnippet0();\
RemoveSpaces0(string);
#define CodeSnippet1();\
RemoveSpaces1(string);
/*======== Конец настроек ====================================================*/
Результаты:
Код:
Тестирование: <native function> vs <Pawn function>
Режим: интерпретируемый, 10000x100 итераций.
native function: 1237
Pawn function: 4601
Код:
Тестирование: <native function> vs <Pawn function>
Режим: с JIT-компиляцией, 10000x100 итераций.
native function: 1464
Pawn function: 472
Как видно по результатам, нативная функция работает в 3.7 раза быстрее кода на Pawn, но при включении JIT результаты меняются вплоть до наоборот: код на Pawn опережает нативную функцию в 3.1 раза.