Mr.Pawn
Умник
Здравствуйте, дорогие пользователи P-I, я прочитал много форумов,тем про оптимизацию модов и об нагрузок на серверов самп,и решил написать тему об том что я узнал, думаю, данная статья пойдёт вам в пользу.
Правда лучше прочитать 1 тему,чем 5-10 и не на одном форуме?!Я не говорю что я придумал всю эту перечисленную оптимизацию,я вам даю советы которые узнал за своё пользование в Pawn и советы других программистов.
Старайтесь использовать в моде как можно меньше таймеров, т.к. каждый таймер увеличивает нагрузку на процессор, и сервер требует больше памяти, в случае этого часто у игроков (вылеты), тормозит и падает сервер.
По оптимизацию таймеров я видел не плохой урок, спасибо за это XemyL
Ещё урок от XemyL,по поводу глобальных таймеров - ТЫК
Ссылка на урок – Клабительно (Не реклама)
не злоупотре***йте этим пабликом, т.к. он обновляется 25 раз в секунду,(как игрок ловит пакеты)да и зависит от пинга игрока, лучше создайте таймер и поместите функцию туда, лучше будет таймер стоять на 1 сек, то есть проверяться 1 раз в секунду, чем будет обновляться этот паблик 25 раз в секунду, а то и больше.
Я часто замечаю многие скриптеры используют функции так:
Но зачем их использовать так?Когда есть более быстрее способ вызвать функцию,через stock,выглядеть это будет вот так:
Можно вот-так.
Только вот функции вызываемые через таймер нельзя поместить в stock,можно рассмотреть вот такой вариант:
Данный макрос от OKStyle позволит вам не форвардить функции таймеров,выглядеть это будет так:
Согласитесь, этот вариант более проще чем этот:
Теперь приступим к глобальной переменной MAX_PLAYERS и MAX_VEHICLES,по умолчанию в a_samp.inc это значение - (MAX_PLAYERS) равно 500,если даже на хостинге 100 слотов,чтобы это исправить, можно определить значение - (MAX_PLAYERS) по новому:
Проверка будет выглядеть вот таким видом:
Есть один минус,вот у нас 100 слотов,а игроков всего 30-40 т.к. мы определили значение - (MAX_PLAYERS) на 100,то у нас будет идти проверка на 100 игроков,ну вот тут есть вот такая функция: GetMaxPlayers(),она определяет онлайн игроков на сервере и сканирует только это количество,на данный момент это 30-40,виглядеть это будет вот так:
Есть один минус,когда у нас будет например 5 игроков с идами: (0,10,15,20,60) то он будет сканировать 61 ид,так вот есть решение это проблемы псевдодинамический массив, для хранения идов подключенных игроков:
В начале мода:
- Создаём глобальный массив
- Переменная содержащая количество игроков на сервере
Очистим весь массив PLIDs,в OnGameModInit:
Операции с глобальными переменными,в OnPlayerConnect:
Игрок подключается, и его ид помещается в последнюю свободную ячейку массива PLIDs, ну а переменная MaxPlayers становится на единицу больше.
С пабликом OnPlayerDisconnect все немного сложнее. Игрок выходит, то есть слот в PLIDs который занимала его ид надо очистить.
Но мне не нужен пустой слот, поэтому я присваиваю ему значение самого последнего слота PLIDs, и вот последний уже очищаю:
Всё,теперь осталось оптимизировать массивы,массив был таким:
После оптимизации:
Также существует инклюд foreach,он считается более лучшим по оптимизации цыкла игроков.
Урок о фориче- (клабительно)
Использование форича на динамических системах - (клабительно)думаю пригодаться вам,Автор - Пельмень
Также есть Vectoral,он намного быстрее чем форич.
Урок взят с темы: Единая тема оптимизации v1 | v2
Автор урока: Tracker1
Решение данной проблемы ниже:
Старайтесь не использовать цыкл в цыкле,пример:
Этот цикл выполнится 500 раз по 500,почему 500?!Потому что глобальная переменная - (MAX_PLAYERS) по умолчанию равна 500,старайтесь не использовать цыкл в цыкле,даже при оптимизации массивов,цыклов,приведёнными выше.
Если вы часто используете один и тот же код,лучше создайте для него функцию,часто это я вижу с GetPlayerName (для узнавания никнейма игрока)пример:
Но опять же мы сталкиваемся с тем что данная функция возвращает строку,а это ведёт к переполнению стека.
Подробней о переполнении стека (клабительно)(Не реклама)
И как же нам быть?!Мы поступим так,как поступил OKStyle:
В enum pInfo добавляем переменную:
В public OnPlayerConnect :
Теперь мы избавимся от переполнении стека из этой функции,но как её использовать?!
Если,вы хотите использовать более удобней то мы добавим макрос:
Пример:
Вот я замечал на некоторых модах не использую табуляцию кода(лесенку),а просто вставляют функцию: #pragma tabsize 0
Насчёт #pragma tabsize 0,советую её не ставить,пусть у вас будет много ошибок от не ровного кода,чем будет стоять эта функция.
Да и в общем лучше не использовать функции на подобие tabsize,они все грузят мод не хило.
Какая ошибка возникает от не ровного кода?! - warning 217: loose indentation
Пример не ровного кода:
Вот таким он будет табуляционным(лесонкой):
Но мы можем этот код оптимизировать,он будет работать намного быстрее,получиться вот так:
Заметьте этот код и следующий я его немного изменил,так будет ещё лучше:
Вы наверно хотите узнать подробней о switch,да без проблем,спасибо за это pozitiv4eg (клабительно)(Не реклама)
Многие думают что,если мод оптимизирован то он будет занимать меньше строк,да это так,но смотря при написании чего-либо пример ниже:
Вот на выше примере,этот код оптимизированный,он занимает 15 строчек.
Этот код не оптимизированный,но занимает 12 строчек,и работает на много медленнее чем первый,думаю вы поняли что,не главное сколько будет строк в коде,главная суть оптимизации это быстрота и эффективность кода.
При создании массивов типа: string[256]; Подумайте заранее,какая самая большая строка может использоваться в массиве,и максимально уменьшите число в квадратных скобках.
Если вы хотите вывести отформатированное функцией format сообщение в чат,максимальное количество символов в сообщении 144,поэтому не логично использовать string[256];
Я видел тут хороший урок про массивы - спасибо Tracker1 (клабительно)(Не реклама)
Старайтесь использовать стандартные функции, в большинстве случаев они быстрее чем их аналоги написанные сторонними скриптерами.
Часто в модах return в таких формах: return true; и return false; лучше их перевести в данную форму:
Я когда ещё не знал об оптимизации мода,мне посоветовали его оптимизировать и всё будет пучком,ну я стал искать мануалы,и вот наткнулся на public OnPlayerCommandText,загляните в свой public OnPlayerCommandText
Посмотрите код на подобие этого new cmd[256]; new tmp[256];
Вот смотрите:
Вот посмотрите внимательно,перед командой /minigun стоит cmd,массив данной переменной равен 256,но зачем нам 256 ячеек???Когда можно поставить 128,т.к в команде максимально 128 ячеек,для данной команды хватает 8 ячеек,то есть new cmd[8];
В среднем в нормальном моде около 100 команд,представьте сколько нагрузки идёт,давайте посмотрим команду по умолчанию:
Заметьте там стоит cmdtext а не cmd,переменная cmdtext используется по умолчанию в паблике,если заменить все cmd на cmdtext и убрать переменную с массивом,то будет на много меньше нагрузки.
На счёт команд,я вам точно сказать не могу,на чём они лучше,т.к не проверял.
Как узнаю,обязательно внесу сюда.
Также я замечал многие используют "быдло код" пример ниже:
Ведь можно сделать вот так:
Ещё одна немаловажная часть, это рейты,при правильной настройке снизится пинг, лаги, нагрузка и пр.
Итак, заходим в server.cfg и там:
Если на вашем сервере играет до 100 человек, то:
Если на вашем сервере играет от 100 до 200 игроков, то:
Если же на вашем сервере играет от 200 до 500 игроков, то:
Перевод:
На счёт античитов,вообще от них идёт тоже нагрузка,мой совет,убрать их с сервера,пусть админы работают!!!Так будет всем интересней,и есть чем заняться админу,у игроков проявиться интерес обмануть и т.д. в последнее время куда не зайди везде античиты,вспомните раньше года 3 назад,особо не были развиты античиты,да и интерес игры больше был!!!
Я помню когда я был навичёк в этому деле,мне один умный скриптер сказал,пусть у тебя будут 20 простых работ,чем 1 сложная.
Я вот по сей день стараюсь придерживаться этого,и вам советую поможет в оптимизации.
На сегодня закончим наш урок,со временем буду дорабатывать,обновлять,испровлять тему,ещё раз повторяю я не всё придумал,я сюда внёс основные виды оптимизации,прошу читателей не писать коментарии на подобие этого:
"я проста пздц как умею аптимизировать моды","бред!" "у миня круче метады!" ""
За новые методы (которых здесь нет),я буду только рад,буду давать плюсы и добавлять в первый пост.
С вами был Mr.Pawn
Правда лучше прочитать 1 тему,чем 5-10 и не на одном форуме?!Я не говорю что я придумал всю эту перечисленную оптимизацию,я вам даю советы которые узнал за своё пользование в Pawn и советы других программистов.
Старайтесь использовать в моде как можно меньше таймеров, т.к. каждый таймер увеличивает нагрузку на процессор, и сервер требует больше памяти, в случае этого часто у игроков (вылеты), тормозит и падает сервер.
По оптимизацию таймеров я видел не плохой урок, спасибо за это XemyL
Ещё урок от XemyL,по поводу глобальных таймеров - ТЫК
Ссылка на урок – Клабительно (Не реклама)
PHP:
OnPlayerUpdate
Я часто замечаю многие скриптеры используют функции так:
PHP:
forward Primer(playerid, model);
public Primer(playerid, model)
{
return true;
}
PHP:
stock Primer(playerid, model)
{
return true;
}
PHP:
Primer(playerid, model)
{
return true;
}
PHP:
#define fpublic %1(%2) forward %1(%2); public %1(%2)
PHP:
fpublic Primer(playerid, model)
{
return true;
}
PHP:
forward Primer(playerid, model);
public Primer(playerid, model)
{
return true;
}
PHP:
#if defined MAX_PLAYERS
#undef MAX_PLAYERS
#define MAX_PLAYERS 100
#else
#define MAX_PLAYERS 100
#endif
PHP:
new Float:health;
for (new i = 0; i < MAX_PLAYERS; i++)
{
if (IsPlayerConnected(i))
{
GetPlayerHealth(i, health);
SetPlayerHealth(i, health + 10.0);
}
}
PHP:
new Float:health;
for (new i = GetMaxPlayers()-1; i != -1; --i)
{
if(!IsPlayerConnected(i)) continue;
if (GetPlayerHealth(i, health)) SetPlayerHealth(i, health + 10.0);
}
В начале мода:
PHP:
new PLIDs[MAX_PLAYERS];
PHP:
new MaxPlayers = 0;
Очистим весь массив PLIDs,в OnGameModInit:
PHP:
for(new i=0;i<sizeof(PLIDs);i++)
{
PLIDs[i] = -1;
}
PHP:
PLIDs[MaxPlayers] = playerid;
MaxPlayers++;
С пабликом OnPlayerDisconnect все немного сложнее. Игрок выходит, то есть слот в PLIDs который занимала его ид надо очистить.
Но мне не нужен пустой слот, поэтому я присваиваю ему значение самого последнего слота PLIDs, и вот последний уже очищаю:
PHP:
for(new i=0;i<MaxPlayers;i++)
{
if(PLIDs[i] == playerid)
{
MaxPlayers--;
PLIDs[i] = PLIDs[MaxPlayers];
PLIDs[MaxPlayers] = -1;
break;
}
}
PHP:
for(new i=0;i<MAX_PLAYERS;i++)
{
if(!IsPlayerConnected(i))
{
continue;
}
SendClientMessage(i, -1, "Пример");
}
PHP:
for(new i=0;i<MaxPlayers;i++)
{
SendClientMessage(PLIDs[i], -1, "Пример");
}
Урок о фориче- (клабительно)
Использование форича на динамических системах - (клабительно)думаю пригодаться вам,Автор - Пельмень
Также есть Vectoral,он намного быстрее чем форич.
Урок взят с темы: Единая тема оптимизации v1 | v2
Автор урока: Tracker1
Теперь давайте поговорим о MAX_VEHICLES,в сампе на данный момент максимум 2000 транспорта,но если у вас 1000 транспорта на сервере то зачем проверять или ещё что либо 2000 транспорта?!Векторы для хранения игроков:
плюсы:
+ БЕШЕННАЯ СКОРОСТЬ ПЕРЕБОРА ВСЕХ ИГРОКОВ.
минусы:
- Твою мать, ни*** не понятно же
#include <Vectoral>
new PLAYERS;
в OnGameModeInit
PLAYERS = cvector();
в соответствующие паблики
public OnPlayerConnect(playerid){ // When player connect
vector_push_back(PLAYERS,playerid); // Insert the player
}
public OnPlayerDisconnect(playerid,reason){
new idx = vector_find(PLAYERS,playerid); // Find player
if(idx !=-1){ // If idx == -1, Vector didn't contains this player
vector_remove(PLAYERS,idx);
}
}
Использование
stock SendMessage(){
for(new idx=0, playerid=0; idx<vector_size(PLAYERS); idx++){ // Цикл
playerid = vector_get(PLAYERS, idx); // Берем плеерид
if(playerid != -1 && GetPlayerTeam(playerid)==NO_TEAM){
SendClientMessage(playerid,0xFFFFAE00,"Чувак, без тимы не круто. Хочешь присоединиться к нам?");
}
}
}
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!
скачать вектора
Решение данной проблемы ниже:
PHP:
#undef MAX_VEHICLES //Отключаем стандартное максимальное количество машин
#define MAX_VEHICLES 1000 //Задаём новое значение, 1000 машин
PHP:
for(new i = 0; i < MAX_PLAYERS; i++)
{
for(new z = 0; z < MAX_PLAYERS; z++)
{
}
}
Если вы часто используете один и тот же код,лучше создайте для него функцию,часто это я вижу с GetPlayerName (для узнавания никнейма игрока)пример:
PHP:
stock PlayerName(playerid)
{
new name[MAX_PLAYER_NAME];
GetPlayerName(playerid,name,sizeof(name));
return name;
}
Подробней о переполнении стека (клабительно)(Не реклама)
И как же нам быть?!Мы поступим так,как поступил OKStyle:
В enum pInfo добавляем переменную:
PHP:
pName[MAX_PLAYER_NAME]
PHP:
GetPlayerName(playerid, PlayerInfo[playerid][pName], MAX_PLAYER_NAME);
PHP:
new str[50];
format(str, sizeof(str), "%s вышел(ла) из игры (Вылет)", PlayerInfo[playerid][pName]);
SendClientMessageToAll(0xffff00AA, str);
PHP:
#define Nick(%1) PlayerInfo[%1][pName]
PHP:
new str[50];
format(str, sizeof(str), "%s вышел(ла) из игры (Вылет)", Nick(playerid));
SendClientMessageToAll(0xffff00AA, str);
Насчёт #pragma tabsize 0,советую её не ставить,пусть у вас будет много ошибок от не ровного кода,чем будет стоять эта функция.
Да и в общем лучше не использовать функции на подобие tabsize,они все грузят мод не хило.
Какая ошибка возникает от не ровного кода?! - warning 217: loose indentation
Пример не ровного кода:
PHP:
if(dialogid == 100)
{
if(response)
{
if(listitem == 0)
{
printf("1");
}
if(listitem == 1)
{
printf("1");
}
if(listitem == 2)
{
printf("1");
}
if(listitem == 3)
{
printf("2");
}
if(listitem == 4)
{
printf("3");
}
if(listitem == 5)
{
printf("4");
}
}
}
PHP:
if(dialogid == 1)
{
if(response)
{
if(listitem == 0)
{
printf("1");
}
if(listitem == 1)
{
printf("1");
}
if(listitem == 2)
{
printf("1");
}
if(listitem == 3)
{
printf("2");
}
if(listitem == 4)
{
printf("3");
}
if(listitem == 5)
{
printf("4");
}
}
}
if(dialogid == 2)
{
if(response)
{
if(listitem == 0)
{
printf("1");
}
if(listitem == 1)
{
printf("2");
}
if(listitem == 2)
{
printf("3");
}
}
}
PHP:
switch(dialogid)
{
case 1://Диалог номер один
{
if(response)
{
switch(listitem)
{
case 0: printf("1");
case 1: printf("1");
case 2: printf("1");
case 3: printf("2");
case 4: printf("3");
case 5: printf("4");
}
}
else
{
//Если в диалоге Кнопка Ок и Отмена,тут будет выполняться действие если нажать отмена,если код пуст от окно закроется
}
}
case 2://Диалог номер 2
{
if(response)
{
switch(listitem)
{
case 0: printf("1");
case 1: printf("2");
case 2: printf("3");
}
}
else
{
//Если в диалоге Кнопка Ок и Отмена,тут будет выполняться действие если нажать отмена,если код пуст от окно закроется
}
}
}
PHP:
switch(dialogid)
{
case 1://Диалог номер один
{
if(response)
{
switch(listitem)
{
case 0..2: printf("1");
case 3..5: printf("%i",listitem-1) ;
}
}
else
{
//Если в диалоге Кнопка Ок и Отмена,тут будет выполняться действие если нажать отмена,если код пуст от окно закроется
return 1;
}
}
case 2://Диалог номер 2
{
if(response)
{
switch(listitem)
{
case 0..2: printf("%i",listitem+1) ;
}
}
else
{
//Если в диалоге Кнопка Ок и Отмена,тут будет выполняться действие если нажать отмена,если код пуст от окно закроется
return 1;
}
}
}
Многие думают что,если мод оптимизирован то он будет занимать меньше строк,да это так,но смотря при написании чего-либо пример ниже:
PHP:
switch(primer)
{
case 0:
{
//Действие
}
case 1:
{
//Действие
}
case 2:
{
//Действие
}
}
PHP:
if(primer == 0)
{
//Действие
}
else if(primer == 1)
{
//Действие
}
else if(primer == 2)
{
//Действие
}
При создании массивов типа: string[256]; Подумайте заранее,какая самая большая строка может использоваться в массиве,и максимально уменьшите число в квадратных скобках.
Если вы хотите вывести отформатированное функцией format сообщение в чат,максимальное количество символов в сообщении 144,поэтому не логично использовать string[256];
Я видел тут хороший урок про массивы - спасибо Tracker1 (клабительно)(Не реклама)
Старайтесь использовать стандартные функции, в большинстве случаев они быстрее чем их аналоги написанные сторонними скриптерами.
Часто в модах return в таких формах: return true; и return false; лучше их перевести в данную форму:
PHP:
return 1;// return true
return 0;//return false
Посмотрите код на подобие этого new cmd[256]; new tmp[256];
Вот смотрите:
PHP:
if(strcmp("/minigun", cmd, true) == 0)
{
return GivePlayerWeapon(playerid, 38, 999999);
}
В среднем в нормальном моде около 100 команд,представьте сколько нагрузки идёт,давайте посмотрим команду по умолчанию:
PHP:
public OnPlayerCommandText(playerid, cmdtext[])
{
if (strcmp("/mycommand", cmdtext, true, 10) == 0)
{
// Do something here
return 1;
}
return 0;
}
На счёт команд,я вам точно сказать не могу,на чём они лучше,т.к не проверял.
Как узнаю,обязательно внесу сюда.
Также я замечал многие используют "быдло код" пример ниже:
PHP:
if(Primer[playerid] == 1)
{
SendClientMessage(playerid, -1, "Пример");
return 1;
}
PHP:
if(Primer[playerid] == 1) return SendClientMessage(playerid, -1, "Пример");
Итак, заходим в server.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
PHP:
onfoot_rate - время в мили секундах за которое будут обновляться координаты перемещения игроков (в ходьбе).
incar_rate - время в мили секундах для обновления позиции транспорта на котором ездят игроки.
weapon_rate - время в мили секундах обновления попадания оружия.
stream_distance - расстояние от игрока к объекту в зоне видимости.
stream_rate - время в мили секундах за которое будут обновляться данные от игрока к объекту.
Я помню когда я был навичёк в этому деле,мне один умный скриптер сказал,пусть у тебя будут 20 простых работ,чем 1 сложная.
Я вот по сей день стараюсь придерживаться этого,и вам советую поможет в оптимизации.
На сегодня закончим наш урок,со временем буду дорабатывать,обновлять,испровлять тему,ещё раз повторяю я не всё придумал,я сюда внёс основные виды оптимизации,прошу читателей не писать коментарии на подобие этого:
"я проста пздц как умею аптимизировать моды","бред!" "у миня круче метады!" ""
За новые методы (которых здесь нет),я буду только рад,буду давать плюсы и добавлять в первый пост.
С вами был Mr.Pawn
Последнее редактирование:
