Доступ к архиву

Переход в группу "Пользователь"

300.00 ₽
Одноразовый платёж
Быстрый переход в группу "Пользователи", без надобности написания постов и ожидания.

Покупка дает возможность:
Быть полноправным участником форума
Нормальное копирование кода
Создавать темы
Скачивать файлы
Доступ к архиву Pawno-Info

Оптимизация

Статус
В этой теме нельзя размещать новые ответы.

© HovinE

Умник
[№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
Это говорит о том что в переменных "string" чересчур большой размер массива.

Чтобы исправить это, делаем следующее..
Например..В начале паблика:
PHP:
public OnPlayerCommandText(playerid, cmdtext[]) 
{ 
    new string[512]; // создали глобальную переменную размером в 512 ячеек. 
}
Теперь в этом же паблике ищем остальные переменные "string" и удаляем, т.к. у нас создана глобальная переменная.
[Важно]: Ищем самый большой format в том паблике, где хотим создать глобальную переменную.
То есть, если в format'е текст в 300 символов, то в начале паблика создаем "new string[356];".​

1.2. Переменные MAX_PLAYERS.

У переменной MAX_PLAYERS дефольно размер массива равен 500 ячейкам, то есть переменная будет работать для первых 500 игроков.
Не у многих серверов онлайн выше 500, так что для первого онлайна лучше сделать следующее:
Ко всем #define:
PHP:
#undef MAX_PLAYERS 
const MAX_PLAYERS = 100;
Если онлайн поднялся до 100-150, то констант объявляйте равной в 200.

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);
COLOR_WHITE - название цвета, то есть можно задефайнить.
Пример..В начале мода:
PHP:
#define COLOR_WHITE 0xFFFFFFAA // Белый
Так, вернемся к оптимизации получения имени игрока. Если постоянно создавать переменные sendername, то можно чокнуться! В смысле категорически не рекомендуется.
Я предлагаю вам версию O.K.Style
В enum pInfo:
PHP:
pName[MAX_PLAYER_NAME]
В public OnPlayerConnect:
PHP:
GetPlayerName(playerid, PlayerInfo[playerid][pName], MAX_PLAYER_NAME);
Теперь все наши "new sendername[MAX_PLAYER_NAME];" и "GetPlayerName(playerid, sendername, sizeof(sendername));" - удаляем.
После..Во всех format'ах "sendername" заменяем на "PlayerInfo[playerid][pName]".
Пример использования:
PHP:
format(string, 64, "%s выиграл гонку!", PlayerInfo[playerid][pName]); 
SendClientMessageToAll(COLOR_WHITE, string);
Как видели во многих командах есть "giveplayerid", так вот..Можно и их оптимизировать!
Делаем следующее..
В начале мода:
PHP:
new giveplayer[MAX_PLAYER_NAME];
В начале public OnPlayerCommandText:
PHP:
new giveplayerid; // создали глобальную переменную
В этом же паблике во всех командах удаляем "new giveplayerid;" и "GetPlayerName(giveplayerid, giveplayer, sizeof(giveplayer));".
Затем во всех format'ах "giveplayer" заменяем на "PlayerInfo[giveplayerid][pName]".
Пример использования:
PHP:
format(string,128,"%s был кикнут Администратором %s.",PlayerInfo[giveplayerid][pName],PlayerInfo[playerid][pName]); 
SendClientMessageToAll(COLOR_WHITE, string); 
Kick(giveplayerid);
Таким образом мы убили 2-ух зайцев, то есть оптимизировали получения имени игрока с двух сторон.

1.5. PVar'ы.

А вот и еще хороший способ оптимизации переменных!
Давайте рассмотрим принцип работы..Например:
PHP:
if(strcmp(cmd, "/pvar", true) == 0) 
{ 
    new randomlol = random(4); 
    SetPVarInt(playerid, "lol", randomlol);
    return true; 
}
Игроку прицепили переменную lol.
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; 
}
Вывод: PVar'ы можно создавать а так же удалять, у PVar'ов маленькая нагрузка, и ими удобно пользоваться.

[№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.
foreach - цикл 21 века
[1] Самый лучший, самый быстрый, самый самый, цикл foreach.
Использовать его можно двумя способами:
PHP:
foreach(Player, i) // 1-ый способ 
foreach(new i : Player) // 2-ой способ
Для работы с этим циклом, нам нужно подключить его. То есть ко всем "#include":
PHP:
#include <foreach>
[№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; 
}
Это мы оптимизировали сами диалоги, теперь приведем наглядный пример не оптимизированного оператора if:
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]++; 
}
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);
Подобных примеров с данным оператором множество! Надеюсь поняли.

[№4 Оптимизация таймеров]:

Обычный вид таймеров:
PHP:
public OnGameModeInit() 
{ 
    SetTimer("Fuel", 1000, 1); 
    SetTimer("Kapt", 1000, 1); 
    SetTimer("GiveHP", 1000*2, 1); 
    return true; 
}
Лучше же конечно использовать все 3 таймера в 1 паблике:
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; 
}
Вывод: таким способом, лучше оптимизировать таймеры которые обновляются с одним и тем же временем!

[№5 Оптимизация рейтов в 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
Если на вашем сервере играет от 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 - время в мили секундах за которое будут обновляться данные от игрока к объекту.

[HR][/HR]
Автор урока - ₥att.
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху Снизу