1. JIT compiler
Он переводит AMX байт-код (код созданный компилятором PAWN) в машинный x86-код, во время выполнения, чтобы ускорить выполнение скрипта.
На самом деле JIT Compiler во много раз ускоряет выполнение скрипта (кода).
В топике, где размещён плагин, размещены и тесты:
Без JIT:
Код:
Test "floatrandom1" finished: 2684ms (3725782.5/sec)
Test "IsPlayerAimingAt" finished: 3004ms (332889.5/sec)
Test "GetPlayerCameraAimVector" finished: 192ms (5208333.5/sec)
С использованием плагина JIT Compiler:
Код:
Test "floatrandom1" finished: 715ms (13986014.0/sec)
Test "IsPlayerAimingAt" finished: 2301ms (434593.6/sec)
Test "GetPlayerCameraAimVector" finished: 22ms (45454548.0/sec)
Если вдруг JIT крашит сервер, попробуйте запустить samp-server.exe с параметром ProcDump и укажите .dmp файл для него. Для этого откройте командную строку, перейдите в каталог с вашим сервером и выполните следующую команду:
PHP код:
path/to/procdump.exe -e -ma -x samp-server.exe samp-server.dmp
Официальная тема JIT Compiler v0.3.2: [Перейти]
2. Строки
Почитайте очень полезный урок от Триггера, который объяснит почему нельзя использовать большие стринги [Перейти]
Так же не стоит возвращать строки в функциях, подробнее в уроке от Владокса: [Перейти]
3. Возвраты
Возьмём за пример следующий код:
PHP код:
new Float:health;
for (new i; i < MAX_PLAYERS; i++)
{
if IsPlayerConnected(i) *then // <----
{
GetPlayerHealth(i, health);
SetPlayerHealth(i, health + 10.0);
}
}
Проверку на то, что игрок подключен в данном случае можно избежать, тем самым оптимизировав и упростив код:
PHP код:
new Float:health;
for (new i; i < MAX_PLAYERS; i++)
{
if GetPlayerHealth(i, health) *then // <-----
SetPlayerHealth(i, health + 10.0);
}
Если игрок не подключен, то функция GetPlayerHealth вернёт 0, тогда цикл пропустит итерацию.
Ещё 1 пример:
PHP код:
if (IsPlayerInAnyVehicle(playerid)) // <-----
{
new vehicleid = GetPlayerVehicleID(playerid);
SetVehiclePos(vehicleid, 0.0, 0.0, 10.0);
}
Проверка на нахождение игрока в автомобиле абсолютно бесполезная, учитывая то, что в дальнейшем узнается id автомобиля, в котором сидит игрок.
Давайте посмотрим на оптимизированную версию этого кода:
PHP код:
new vehicleid = GetPlayerVehicleID(playerid);
if (vehicleid)
SetVehiclePos(vehicleid, 0.0, 0.0, 10.0);
Если игрок не в автомобиле, то функция GetPlayerVehicleID вернет 0, собственно код ниже не выполнится.
Отсюда становится ясно, что условие нахождение игрока в автомобиле не нужно.
4. Циклы
Вот пример оптимизированного цикла:
PHP код:
for(new i,zx = GetMaxPlayers( ); i < zx; i++)
{
if !IsPlayerConnected(i) *then continue; //В некоторых случаях можно поставить проверку на флаг логина (если не залогинен)
//Действие
}
Это один из способов оптимизации циклов игроков.
Второй (более быстрый) способ от пользователя официального форума Y_Less'а.
Он создал инклуд под названием foreach и сейчас я постараюсь объяснить как им пользоваться.
Пример:
PHP код:
foreach(Player, i)
{
//Действие
}
Это очень быстрый метод сканирования игроков, постараюсь объяснить.
Допустим играют на сервере 3 человека, id последнего - 25.
Цикл foreach сделает 3 итерации, в отличии от остальных.
Скачать foreach: [Скачать]
Подключать его легко, закиньте его в папку include в вашей папке с pawno и далее в моде/скрипте/инклуде:
PHP код:
#include foreach
5. Функции
В стандартном GF функции создаются примерно так:
PHP код:
forward Func(playerid, gunid);
public Func(playerid, gunid)
{
return true;
}
Есть ещё 2 способа создания функций и они намного быстрее, нежели первый:
PHP код:
stock Func(playerid, gunid)
{
}
Func(playerid, gunid)
{
}
Таким образом создавать функции намного удобнее и лучше, кстати, я рекомендую способ напрямую создания функции (Func (playerid, gunid) ), т.к если функция в коде не применялось, то компилятор выдаст warining.
6. Переменные MAX_PLAYERS
Часто сталкивался с таким кодом как:
PHP код:
new Player[MAX_PLAYERS];
public OnPlayerConnect(playerid)
{
Player[playerid] += 1;
}
Дефолтно переменная MAX_PLAYERS равна 500.
Т.е мы создаём массив с 500 ячейками, а если максимальное кол-во слотов на сервере - 100, то для этого используем следующий код:
PHP код:
#undef MAX_PLAYERS // Раздефайним макрос MAX_PLAYERS
#assert MAX_PLAYERS > 0
#define MAX_PLAYERS 100 //Объявим константу, равную 100
7. Получение имени игрока
Всё чаще начал замечать следующую функцию для получения ника игрока:
PHP код:
forward GN(playerid);
public GN(playerid)
{
new PlayerName[MAX_PLAYER_NAME];
GetPlayerName(playerid,PlayerName,sizeof(PlayerName));
return PlayerName;
}
Категорически не рекомендую это использовать, т.к у данной функции есть 2 больших минуса:
1. При каждом использовании создается переменная PlayerName
2. Функция возвращает строку, а это не хорошо
Вот как можно это оптимизировать:
В энуменатор игроков добавляем переменную:
PHP код:
pName[MAX_PLAYER_NAME]
В public OnPlayerConnect :
PHP код:
GetPlayerName(playerid, PlayerInfo[playerid][pName], MAX_PLAYER_NAME);
Далее ко всем макросам:
#define GN(%1) PlayerInfo[%1][pName]
И всё, теперь без переполнения стека можно определять ник игрока, это очень большой плюс к оптимизации.
Пример использования:
PHP код:
printf("%s был замечен на сервере", GN(playerid));
8. Switch vs Оператор ветвления if/else/else if
В большинстве случаев оператор switch выигрывает в скорости.
Switch работает быстрее в тех случаях, когда нужно перебрать большое кол-во значений.
К примеру диалоги, в большинстве модах много диалогов и оператором if их перебирать не разумно.
Приведём пример как было:
PHP код:
if(dialogid == 100)
{
if(response)
{
if(listitem == 0)
{
print("1");
}
if(listitem == 1)
{
print("1");
}
if(listitem == 2)
{
print("1");
}
if(listitem == 3)
{
print("2");
}
if(listitem == 4)
{
print("3");
}
if(listitem == 5)
{
print("2");
}
}
}
else if(dialogid == DIALOG_LOGIN)
{
if(response)
{
//Действие
}
}
и как стало:
PHP код:
switch(dialogid)
{
case 100:
{
if(!response) return true;
switch(listitem)
{
case 0..2: print("1");
case 3,5: print("2");
case 4: print("3");
}
}
case DIALOG_LOGIN:
{
if(!response) return 1;
}
}
В каких случаях лучше использовать switch:
Следующая конструкция:
PHP код:
switch(var)
{
case 40,80,150,160,230,420: return 1;
}
быстрее, чем
PHP код:
if ( var == 40 || var == 80 || var == 150 || var == 160 || var == 230 || var == 420 ) return 1;
Следующая конструкция:
PHP код:
switch(var)
{
case 40..80,150..160,230..420: return 1;
}
медленнее чем
PHP код:
if ( var >= 40 && var <= 80 || var >= 150 && var <= 160 || var >= 230 && var <= 420 ) return 1;
Следующая конструкция:
PHP код:
switch(var)
{
case 40: return 1;
}
одинакова как и
PHP код:
if ( var == 40 ) return 1;
Следующая конструкция:
PHP код:
switch(var)
{
case 40..50: return 1;
}
быстрее чем
PHP код:
if ( var >= 40 && var <= 50 ) return 1;
9. Команды
Наиболее быстрый плагин для создания команд - DC_CMD
Вот ссылка: http://pawno.su/showthread.php?t=96066
P.S: Если знаете более быстрый способ, отпишитесь в комментариях
10. Рейты
Ещё одна немаловажная часть, это рейты.
При правильной настройке снизится пинг, лаги, нагрузка и пр.
Итак, заходим в server.cfg и там:
Если на вашем сервере играет до 100 человек, то:
PHP код:
onfoot_rate 40
incar_rate 40
weapon_rate 40
stream_distance 400.0
stream_rate 500
Если на вашем сервере играет от 100 до 200 игроков, то:
PHP код:
onfoot_rate 40
incar_rate 40
weapon_rate 40
stream_distance 300.0
stream_rate 1000
Если же на вашем сервере играет от 200 до 500 игроков, то:
PHP код:
onfoot_rate 50
incar_rate 50
weapon_rate 50
stream_distance 200.0
stream_rate 2000
onfoot_rate - время в мили секундах за которое будут обновляться координаты перемещения игроков (в ходьбе).
incar_rate - время в мили секундах для обновления позиции транспорта на котором ездят игроки.
weapon_rate - время в мили секундах обновления попадания оружия.
stream_distance - расстояние от игрока к объекту в зоне видимости.
stream_rate - время в мили секундах за которое будут обновляться данные от игрока к объекту.
10. Оптимизация потребления памяти
Приведу простой пример оптимизации потребления памяти на переменных.
Возьмём для примера 2 переменные:
1.
PHP код:
new a[MAX_PLAYERS];
a[1] = 100;
2.
PHP код:
new a[MAX_PLAYERS char];
a{1} = 100;
heapspace MAX_PLAYERS: 2004
heapspace MAX_PLAYERS char: 504
Результат на лицо.
Однако не спешите ко всем массивам приписывать char, давайте приглядимся.
Фигурные скобки обозначают, что мы обращаемся к байту, а не к ячейке и главной нашей проблемой является то, что 1 байт хранит значения от 0 до 255 (включительно).
А это значит, что использовать char нужно осмотрительно и с умом.
• Так же, для экономии памяти вы можете использовать флаги: [Перейти]