₥att
Ученик
Оптимизация [ALL]
Приветствую вас дорогие форумчане портала pawno-info.
В этом уроке я попытаюсь более подробно объяснить все виды оптимизаций.
[№1 Оптимизация переменных]:
1.1. Переполненные стоки или как оптимизировать string'и.
Во многих RLS модах при компиляции можно встретить такое:
Это говорит о том что в переменных "string" чересчур большой размер массива.
Чтобы исправить это, делаем следующее..
Например..В начале паблика:
Теперь в этом же паблике ищем остальные переменные "string" и удаляем, т.к. у нас создана глобальная переменная.
1.2. Переменные MAX_PLAYERS.
У переменной MAX_PLAYERS дефольно размер массива равен 500 ячейкам, то есть переменная будет работать для первых 500 игроков.
Не у многих серверов онлайн выше 500, так что для первого онлайна лучше сделать следующее:
Ко всем #define:
Если онлайн поднялся до 100-150, то констант объявляйте равной в 200.
1.3. format'ы.
Создав одну глобальную переменную "new string[512];"..
fomat лучше будет использовать так:
чем так:
При запуске возьмет 1КБ от оперативки, а стека брать не будет.
1.4. Получение имени игрока.
Практически в каждом коде можно встретить такое:
COLOR_WHITE - название цвета, то есть можно задефайнить.
Пример..В начале мода:
Так, вернемся к оптимизации получения имени игрока. Если постоянно создавать переменные sendername, то можно чокнуться! В смысле категорически не рекомендуется.
Я предлагаю вам версию O.K.Style
В enum pInfo:
В public OnPlayerConnect:
Теперь все наши "new sendername[MAX_PLAYER_NAME];" и "GetPlayerName(playerid, sendername, sizeof(sendername));" - удаляем.
После..Во всех format'ах "sendername" заменяем на "PlayerInfo[playerid][pName]".
Пример использования:
Как видели во многих командах есть "giveplayerid", так вот..Можно и их оптимизировать!
Делаем следующее..
В начале мода:
В начале public OnPlayerCommandText:
В этом же паблике во всех командах удаляем "new giveplayerid;" и "GetPlayerName(giveplayerid, giveplayer, sizeof(giveplayer));".
Затем во всех format'ах "giveplayer" заменяем на "PlayerInfo[giveplayerid][pName]".
Пример использования:
Таким образом мы убили 2-ух зайцев, то есть оптимизировали получения имени игрока с двух сторон.
1.5. Пвары.
А вот и еще хороший способ оптимизации переменных!
Давайте рассмотрим принцип работы..Например:
Игроку прицепили переменную lol.
Вывод: пвары можно создавать а так же удалять, у пваров маленькая нагрузка, и ими удобно пользоваться.
[№2 Оптимизация циклов]:
2.1. for или foreach?.
Циклы в pawn играют не маловажную роль.
Существует 3 вида цикл. Каждый лучше другого.
[3] Самый отвратительный цикл из всех что я видел:
Но! Существует и оптимизированный цикл, который явно лучше написанного чуть выше.
[2] Оптимизированный цикл:
Да, он хорош, но не с foreach.
foreach - цикл 21 века
[1] Самый лучший, самый быстрый, самый самый, цикл foreach.
Скачать инклуд foreach: [
Пароль от скачивания: pawno-info
Установка: Заходим в папку нашего сервера, затем pawno/include/сюда помещаем файл "foreach.inc".
Использовать его можно двумя способами:
Для работы с этим циклом, нам нужно подключить его. То есть ко всем "#include":
[№3 Оптимизация операторов]:
3.1. switch или if?.
Во сновном оператор switch выигрывает в скорости, чем if.
Switch быстрее только в тех случаях, когда нужно перебрать большое кол-во значений.
Пример не оптимизированных диалогов:
А вот как будет выглядеть в оптимизированном виде:
Это мы оптимизировали сами диалоги, теперь приведем наглядный пример не оптимизированного оператора if:
Можно оптимизировать таким образом:
Да, оптимизация тут не ахти 
А теперь давайте оптимизируем оператором switch:
или так:
3.2. Тернарные операторы.
Тернарный оператор - тоже что и конструкция if..then..else.
Но тернарный оператор применяется в виде одно-строчной функции.
Использование оператора:
логическое выражение ? выражение 1 : выражение 2
Использование конструкцией if..then..else:
if(логическое выражение) then выражение 1 else выражение 2
Наглядный пример использование тернарного оператора:
Из этого давайте приведем пример:
Таким образом мы сделали проверку на наличие денег и действие в одну строку!
Можно так:
Подобных примеров с данным оператором множество! Надеюсь поняли.
[№4 Оптимизация таймеров]:
Обычный вид таймеров:
Лучше же конечно использовать все 3 таймера в 1 паблике:
Теперь в него добавляем паблики которые обновляются каждую секунду:
Сам пример использования:
До оптимизации:
После Оптимизации:
Вывод: таким способом, лучше оптимизировать таймеры которые обновляются с одним и тем же временем!
[№5 Оптимизация функций]:
Обычно стандартные функции создаются так:
Мне кажется это как то стремно..
И снова я предлагаю вам версию O.K.Style
Ко всем "#define":
То есть мы создали макрос, благодаря которому нам не придется создавать forward'ы.
Использование макроса:
[№6 Оптимизация рейтов в server.cfg]:
Давайте вспомним что говорил Doc_Slove:
"Ещё одна немаловажная часть, это рейты.
При правильной настройке снизится пинг, лаги, нагрузка и пр."
Все правильно, поэтому я и предложу вам его настройки server'a.cfg
Если на вашем сервере играет до 100 человек, то:
Если на вашем сервере играет от 100 до 200 игроков, то:
Если же на вашем сервере играет от 200 до 500 игроков, то:
[Практика] Оптимизация кода:
Теория теорией, а без практики никуда.
Давайте все выше прочитанное испробуем на команде kick.
[1] Не оптимизированная команда /kick:
Посмотрев на этот код, захочется повеситься 
Теперь давайте оптимизируем код:
Вы спросите, куда делись переменные: new giveplayerid,result[64],sendername[MAX_PLAYER_NAME],giveplayer[MAX_PLAYER_NAME];
Ответ прост! Они в начале паблика, кроме sendername,giveplayer. Получается эти переменные - глобальные.
Вот в принципе и все.
Всем спасибо.
[HR][/HR]
Автор данной статьи - Я. ©
Приветствую вас дорогие форумчане портала pawno-info.
В этом уроке я попытаюсь более подробно объяснить все виды оптимизаций.
[№1 Оптимизация переменных]:
1.1. Переполненные стоки или как оптимизировать string'и.
Во многих RLS модах при компиляции можно встретить такое:
PHP:
Header size: 4380 bytes
Code size: 215680 bytes
Data size: 226524 bytes
Stack/heap size: 16384 bytes; estimated max. usage: unknown, due to recursion
Total requirements: 462968 bytes
Чтобы исправить это, делаем следующее..
Например..В начале паблика:
PHP:
public OnPlayerCommandText(playerid, cmdtext[])
{
new string[512]; // создали глобальную переменную размером в 512 ячеек.
}
[Важно]: Ищем самый большой format в том паблике, где хотим создать глобальную переменную.
То есть, если в format'е текст в 300 символов, то в начале паблика создаем "new string[356];".
То есть, если в format'е текст в 300 символов, то в начале паблика создаем "new string[356];".
+1 к оптимизации.
1.2. Переменные MAX_PLAYERS.
У переменной MAX_PLAYERS дефольно размер массива равен 500 ячейкам, то есть переменная будет работать для первых 500 игроков.
Не у многих серверов онлайн выше 500, так что для первого онлайна лучше сделать следующее:
Ко всем #define:
PHP:
#undef MAX_PLAYERS
const MAX_PLAYERS = 100;
+1 к оптимизации.
1.3. format'ы.
Создав одну глобальную переменную "new string[512];"..
fomat лучше будет использовать так:
PHP:
format(string,64,"%s выиграл гонку!",PlayerInfo[playerid][pName])
SendClientMessageToAll(0xFFFFFFAA, string);
PHP:
format(string,sizeof(string),"%s выиграл гонку!",PlayerInfo[playerid][pName])
SendClientMessageToAll(0xFFFFFFAA, string);
+1 к оптимизации.
1.4. Получение имени игрока.
Практически в каждом коде можно встретить такое:
PHP:
// почему нету переменной string?
// -да потому что мы создали глобальную переменную
new sendername[MAX_PLAYER_NAME];
GetPlayerName(playerid, sendername, sizeof(sendername));
format(string, 64, "%s выиграл гонку!", sendername);
SendClientMessageToAll(COLOR_WHITE, string);
Пример..В начале мода:
PHP:
#define COLOR_WHITE 0xFFFFFFAA // Белый
Я предлагаю вам версию O.K.Style
В enum pInfo:
PHP:
pName[MAX_PLAYER_NAME]
PHP:
GetPlayerName(playerid, PlayerInfo[playerid][pName], MAX_PLAYER_NAME);
После..Во всех format'ах "sendername" заменяем на "PlayerInfo[playerid][pName]".
Пример использования:
PHP:
format(string, 64, "%s выиграл гонку!", PlayerInfo[playerid][pName]);
SendClientMessageToAll(COLOR_WHITE, string);
Делаем следующее..
В начале мода:
PHP:
new giveplayer[MAX_PLAYER_NAME];
PHP:
new giveplayerid; // создали глобальную переменную
Затем во всех format'ах "giveplayer" заменяем на "PlayerInfo[giveplayerid][pName]".
Пример использования:
PHP:
format(string,128,"%s был кикнут Администратором %s.",PlayerInfo[giveplayerid][pName],PlayerInfo[playerid][pName]);
SendClientMessageToAll(COLOR_WHITE, string);
Kick(giveplayerid);
+1 к оптимизации.
1.5. Пвары.
А вот и еще хороший способ оптимизации переменных!
Давайте рассмотрим принцип работы..Например:
PHP:
if(strcmp(cmd, "/pvar", true) == 0)
{
new randomlol = random(4);
switch(randomlol)
{
case 0: SetPVarInt(playerid, "lol", 1); // "lol" название переменной. 1 - значение
case 1: SetPVarInt(playerid, "lol", 2);
case 2: SetPVarInt(playerid, "lol", 3);
default: SetPVarInt(playerid, "lol", 4);
}
return true;
}
PHP:
if(strcmp(cmd, "/priz", true) == 0)
{
if(GetPVarInt(playerid, "lol") != 1) return true; // проверка переменной lol. если lol не равняется 1, то никакого действия
GivePlayerMoney(playerid, 1000);
DeletePVar(playerid, "lol"); // удалили пвар, то есть отцепили от игрока. а вот с new такие штучки не пройдут!
return true;
}
+1 к оптимизации.
[№2 Оптимизация циклов]:
2.1. for или foreach?.
Циклы в pawn играют не маловажную роль.
Существует 3 вида цикл. Каждый лучше другого.
[3] Самый отвратительный цикл из всех что я видел:
PHP:
for(new i = 0; i < MAX_PLAYERS; i++)
[2] Оптимизированный цикл:
PHP:
for(new i = GetMaxPlayers() - 1; i != -1; i--)
foreach - цикл 21 века
[1] Самый лучший, самый быстрый, самый самый, цикл foreach.
Скачать инклуд foreach: [
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!
]Пароль от скачивания: pawno-info
Установка: Заходим в папку нашего сервера, затем pawno/include/сюда помещаем файл "foreach.inc".
Использовать его можно двумя способами:
PHP:
foreach(Player, i) // 1-ый способ
foreach(new i : Player) // 2-ой способ
PHP:
#include <foreach>
+1 к оптимизации.
[№3 Оптимизация операторов]:
3.1. switch или if?.
Во сновном оператор switch выигрывает в скорости, чем if.
Switch быстрее только в тех случаях, когда нужно перебрать большое кол-во значений.
Пример не оптимизированных диалогов:
PHP:
if(dialogid == 1)
{
if(response)
{
new listitems[] = "1) Создать пвар\n2) Удалить пвар";//
ShowPlayerDialog(playerid, 2, DIALOG_STYLE_LIST, "Пвары", listitems, "Выбрать", "Отмена");
}
}
if(dialogid == 2)
{
if(response)
{
if(listitem == 0)
{
SetPVarInt(playerid, "lol", 1);
SendClientMessage(playerid, COLOR_WHITE, "Ты создал переменную lol.");
}
if(listitem == 1)
{
DeletePVar(playerid, "lol");
SendClientMessage(playerid, COLOR_WHITE, "Ты удалил переменную lol.");
}
}
else
{
SendClientMessage(playerid, COLOR_WHITE, "Ты выключил меню пваров!");
}
return true;
}
PHP:
switch(dialogid)
{
case 1:
{
if(!response) return true;
ShowPlayerDialog(playerid, 2, DIALOG_STYLE_LIST, "Пвары", "1) Создать пвар\n2) Удалить пвар", "Выбрать", "Отмена");
}
case 2:
{
if(!response) return SendClientMessage(playerid, COLOR_WHITE, "Ты выключил меню пваров!");
switch(listitem)
{
case 0: { SetPVarInt(playerid, "lol", 1); SendClientMessage(playerid, COLOR_WHITE, "Ты создал переменную lol."); }
default: { DeletePVar(playerid, "lol"); SendClientMessage(playerid, COLOR_WHITE, "Ты удалил переменную lol."); }
}
}
return true;
}
PHP:
if(PlayerInfo[playerid][pRassa] == 1)
{
PlayerInfo[playerid][pRassa] = 2;
}
if(PlayerInfo[playerid][pRassa] == 3)
{
PlayerInfo[playerid][pRassa] = 4;
}
if(PlayerInfo[playerid][pRassa] == 5)
{
PlayerInfo[playerid][pRassa] = 6;
}
PHP:
if(PlayerInfo[playerid][pRassa] == 1) PlayerInfo[playerid][pRassa] = 2;
else if(PlayerInfo[playerid][pRassa] == 3) PlayerInfo[playerid][pRassa] = 4;
else if(PlayerInfo[playerid][pRassa] == 5) PlayerInfo[playerid][pRassa] = 6;
А теперь давайте оптимизируем оператором switch:
PHP:
switch(PlayerInfo[playerid][pRassa])
{
case 1: PlayerInfo[playerid][pRassa] = 2;
case 3: PlayerInfo[playerid][pRassa] = 4;
case 5: PlayerInfo[playerid][pRassa] = 6;
}
PHP:
switch(PlayerInfo[playerid][pRassa])
{
case 1,3,5: PlayerInfo[playerid][pRassa]++;
}
+1 к оптимизации.
3.2. Тернарные операторы.
Тернарный оператор - тоже что и конструкция if..then..else.
Но тернарный оператор применяется в виде одно-строчной функции.
Использование оператора:
логическое выражение ? выражение 1 : выражение 2
Использование конструкцией if..then..else:
if(логическое выражение) then выражение 1 else выражение 2
Наглядный пример использование тернарного оператора:
PHP:
new a, b;
z = (a == 0) ? 0 : 1;
PHP:
GivePlayerMoney(playerid, (PlayerInfo[playerid][pCash] > 1000) ? -1000 : SendClientMessage(playerid,COLOR_WHITE,"Недостаточно!"));
Можно так:
PHP:
SetPlayerHealth(playerid, (PlayerInfo[playerid][pAdmin] > 1) ? 100.0 : 50.0);
+1 к оптимизации.
[№4 Оптимизация таймеров]:
Обычный вид таймеров:
PHP:
public OnGameModeInit()
{
SetTimer("Fuel", 1000, 1);
SetTimer("Kapt", 1000, 1);
SetTimer("GiveHP", 1000*2, 1);
return true;
}
PHP:
public OnGameModeInit()
{
SetTimer("TimersUpdate", 1000, 1);
return true;
}
PHP:
Public TimerUpdate()
{
Fuel();
Kapt();
// заметьте! я не добавил паблик "GiveHP" т.к. он обновляется каждые 2 секунды
return true;
}
До оптимизации:
PHP:
public OnGameModeInit()
{
SetTimer("Fuel", 1000, 1);
SetTimer("Kapt", 1000, 1);
SetTimer("GiveHP", 1000*2, 1);
return true;
}
forward Fuel();
Public Fuel()
{
return true;
}
forward Kapt();
Public Kapt()
{
return true;
}
forward GiveHP();
Public GiveHP()
{
return true;
}
PHP:
public OnGameModeInit()
{
SetTimer("TimersUpdate", 1000, 1);
SetTimer("GiveHP", 1000*2, 1);
return true;
}
forward TimersUpdate();
Public TimersUpdate()
{
Fuel();
Kapt();
return true;
}
stock Fuel()
{
return true;
}
stock Kapt()
{
return true;
}
forward GiveHP();
Public GiveHP()
{
return true;
}
+1 к оптимизации.
[№5 Оптимизация функций]:
Обычно стандартные функции создаются так:
PHP:
forward Lol(playerid, vehicleid);
public Lol(playerid)
{
return true;
}
И снова я предлагаю вам версию O.K.Style
Ко всем "#define":
PHP:
#define dpublic %1(%2) forward %1(%2); public %1(%2)
Использование макроса:
PHP:
dpublic Lol(playerid, vehicleid)
{
return true;
}
+1 к оптимизации.
[№6 Оптимизация рейтов в server.cfg]:
Давайте вспомним что говорил Doc_Slove:
"Ещё одна немаловажная часть, это рейты.
При правильной настройке снизится пинг, лаги, нагрузка и пр."
Все правильно, поэтому я и предложу вам его настройки server'a.cfg
Если на вашем сервере играет до 100 человек, то:
PHP:
onfoot_rate 40
incar_rate 40
weapon_rate 40
stream_distance 400.0
stream_rate 500
PHP:
onfoot_rate 40
incar_rate 40
weapon_rate 40
stream_distance 300.0
stream_rate 1000
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 - время в мили секундах за которое будут обновляться данные от игрока к объекту.
incar_rate - время в мили секундах для обновления позиции транспорта на котором ездят игроки.
weapon_rate - время в мили секундах обновления попадания оружия.
stream_distance - расстояние от игрока к объекту в зоне видимости.
stream_rate - время в мили секундах за которое будут обновляться данные от игрока к объекту.
+1 к оптимизации.
[Практика] Оптимизация кода:
Теория теорией, а без практики никуда.
Давайте все выше прочитанное испробуем на команде kick.
[1] Не оптимизированная команда /kick:
PHP:
if(strcmp(cmd, "/kick", true) == 0)
{
if(IsPlayerConnected(playerid))
{
tmp = strtok(cmdtext, idx);
if(!strlen(tmp))
{
SendClientMessage(playerid, COLOR_GRAD2, "{ffffff}*Используйте: /kick [ID игрока] [Причина]");
return 1;
}
new sendername[MAX_PLAYER_NAME];
new giveplayer[MAX_PLAYER_NAME];
new giveplayerid;
giveplayerid = ReturnUser(tmp);
if(PlayerInfo[playerid][pAdmin] >= 1)
{
if(IsPlayerConnected(giveplayerid))
{
if(giveplayerid != INVALID_PLAYER_ID)
{
GetPlayerName(giveplayerid, giveplayer, sizeof(giveplayer));
GetPlayerName(playerid, sendername, sizeof(sendername));
new length = strlen(cmdtext);
while ((idx < length) && (cmdtext[idx] <= ' '))
{
idx++;
}
new offset = idx;
new result[64];
while ((idx < length) && ((idx - offset) < (sizeof(result) - 1)))
{
result[idx - offset] = cmdtext[idx];
idx++;
}
result[idx - offset] = EOS;
if(!strlen(result))
{
SendClientMessage(playerid, COLOR_GRAD2, "{ffffff}* Помощь: /kick [ID игрока] [Причина]");
return 1;
}
format(string, sizeof(string), "%s был кикнут администратором %s, Причина: %s", giveplayer, sendername, (result));
SendClientMessageToAll(COLOR_LIGHTRED, string);
Kick(giveplayerid);
return 1;
}
}
}
else
{
format(string, sizeof(string), "%d не в сети", giveplayerid);
SendClientMessage(playerid, COLOR_GRAD1, string);
}
}
}
return true;
}
Теперь давайте оптимизируем код:
PHP:
if(strcmp(cmd, "/kick", true) == 0)
{
if(!IsPlayerConnected(playerid)) return true;
if(PlayerInfo[playerid][pAdmin] == 0) return true;
tmp = strtok(cmdtext, idx);
if(!strlen(tmp)) return SendClientMessage(playerid, COLOR_GRAD2, "{ffffff}*Используйте: /kick [ID игрока] [Причина]");
giveplayerid = ReturnUser(tmp);
if(!IsPlayerConnected(giveplayerid)) return true;
if(giveplayerid == playerid) return SendClientMessage(playerid, COLOR_WHITE, "[Ошибка] Вы ввели свой ID.");
new length = strlen(cmdtext);
while ((idx < length) && (cmdtext[idx] <= ' '))
{
idx++;
}
new offset = idx;
while ((idx < length) && ((idx - offset) < (sizeof(result) - 1)))
{
result[idx - offset] = cmdtext[idx];
idx++;
}
result[idx - offset] = EOS;
if(!strlen(result)) return SendClientMessage(playerid, COLOR_GRAD2, "{ffffff}* Помощь: /kick [ID игрока] [Причина]");
format(string, 128, "%s был кикнут администратором %s, Причина: %s", PlayerInfo[giveplayerid][pName], PlayerInfo[playerid][pName], result);
SendClientMessageToAll(COLOR_LIGHTRED, string);
Kick(giveplayerid);
return true;
}
Ответ прост! Они в начале паблика, кроме sendername,giveplayer. Получается эти переменные - глобальные.
Вот в принципе и все.
Всем спасибо.
[HR][/HR]
Автор данной статьи - Я. ©
Копипаст строго запрещен!
Подпись: ₥эт
Последнее редактирование:
