Оптимизация мода/скрипта. Оптимизация pawno


Оптимизация мода/скрипта - Изучаем язык pawn

Совет #1:Используйте в скрипте/моде как можно меньше таймеров. Каждый таймер способствует постепенному нарастанию грыжи у сервера.Совет #2:Функции которые не используются в таймерах, помещайте в stock а не в publicСовет #3:При создании массивов типа:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Подумайте заранее, какая самая большая строка может использоваться в массиве, и максимально уменьшите число в квадратных скобках.Макс. знчение для SendClientMessage 144.Совет #4:Соблюдайте табуляцию/выравнивание кода (лесенка) и не используйте функций типо tabsize.Совет #5:В некоторых случаях лучше использовать функцию напрямую, чем заводить для неё переменную.Пример:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Лучше сделать так:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Совет #6:Если в переменной может быть значение только 0 или 1, используйте тип переменной bool.Пример:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Совет #7:Старайтесь меньше использовать такие константы как MAX_PLAYERS, MAX_VEHICLES и т.п.Лучше сделать так:#undef MAX_PLAYERS #define MAX_PLAYERS 20где 20 - новое значение константыСовет #8:Старайтесь использовать стандартные функции, в большинстве случаев они быстрее чем их аналоги написанные сторонними скриптерами.Яркий пример: PlayerToPoint и IsPlayerRangeOfPointСовет #9:В некоторых случаях лучше использовать switch нежели if/elseПример:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Лучше записать так:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Совет #10:Если возможно, лучше использовать имя клавиши, нежели её код.Пример:Клавиша Alt: KEY_WALK/1024Лучше записать KEY_WALK.Совет #11:В большинстве случаев, использование паблика OnPlayerUpdate не оправдывает само себя, поэтому лучше с ним не злоупотреблятb.Совет #12:НИКОГДА не используйте цикл в цикле (последнее время частенько такое замечаю).Пример:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Совет #13:Если вы часто используете один и тот же код, лучше создать для него функцию.Пользуясь этими советами, вы добьётесь большей эффективности скриптинга. Как в быстродействии, так и в визуальном восприятии кода.А теперь пара приёмов "оптимизированного" кода.1. Структура switch:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Лучше записать так:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

2. Часто в функциях/командах используется:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

"Функцию" return, можно использовать в составе с любой функцией которая возвращает 1 или 0 (истина или ложь).В нашем примере можно сделать так:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

2.1. Если функция возвращает true/else по условию:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Можно записать так:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

3. Использование псевдодинамических массивов для оптимизации циклов типа:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

==============================================================================================Оптимизация циклов вида:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Не для кого не секрет, что MAX_PLAYERS определяется в a_samp.inc и равна 500.Раньше я использовал вот такую манипуляцию:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Это конечно давало некоторый прирост, но я пошел еще дальше!Первой идеей было использовать функцию GetMaxPlayers(), но это никак не помогло бы: на сервере могут быть всего 3 игрока, ид которых 0, 7 и 28, и циклу приходилось бы совершать 28 тактов.К сожалению, в pawn нельзя создавать динамические массивы, поэтому я придумал использовать что-то вроде псевдодинамического массива для хранения идподключенных игроков. Создал глобальный масив:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Далее я ввел переменную содержащую количество игроков на сервере:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Теперь надо добавить в паблик OnPlayerConnect необходимые операции с глобальными переменными:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Все довольно просто - игрок подключается, и его ИД помещается в последнюю свободную ячейку массива PLIDs, ну а переменная MaxPlayers становится на единицу больше.С пабликом OnPlayerDisconnect все немного сложнее. Игрок выходит, тоесть слот в PLIDs который занимала его ИД надо очистить. Но мне не нужен пустой слот, поэтому я присваиваю ему значение самого последнего слота PLIDs, и вот последний уже очищаю:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Все, теперь вы можете оптимизировать массивы.Пример:Пусть был массив:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

После оптимизации:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Плюсы данного метода:- отсутствуют лишние такты циклов- не требуется проверять подключен ли игрокМинусы:- меняется порядок ИД игроков при выполнении циклов==============================================================================================4. Использование массива вместо функции GetPlayerName (либо ее аналога, GetPlayerNameEx) для узнавания никнейма игрока.Для этого создаем глобальный двумерный массив:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Далее в OnPlayerConnect'e записываем никнейм игрока в массив:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

При каждом изменении ника по сценарию мода также добавляем эту строку (например в команду /setname)При выходе игрока нужно очистить его ячейку в массиве:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Пример использование:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Автор: eFFect aka YoYo

pawno-crmp.ru

Оптимизация - Изучаем язык pawn

Часть 1. Циклы

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

В этом цикле всем игрокам сервера максимально быстро установится 100 единиц брони. А теперь давайте разберём интересные моменты по "кусочкам":

 

new i = GetMaxPlayers() - 1; - данная запись создаст переменную, величина которой будет равняться количеству слотов, записанных в конфиге сервера, но так как всего 800 игроков, то ID будут от 0 до 799, поэтому -1.

i != 0 - самое быстрое сравнение - не равно. В нашем случае мы ждём момента, пока уменьшаемая переменная не достигнет нуля.

--i - префиксный декремент, который сначала уменьшит переменную, а потом подставит её в цикл. (если писать i--, то нужно выполнять сравнение i != -1). Почему именно он? Потому что уменьшение переменной происходит быстрее, чем увеличение.

if(!IsPlayerConnected(i)) continue; - если игрок отсутствует на сервере, сразу переходим к следующей итерации, игнорируя дальнейшие условия.

if(IsPlayerNPC(i)) continue; - если игрок - бот, запускаем следующую итерацию.

 

В случае, когда нужно найти циклом игрока с определённым именем:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

В данном цикле мы максимально быстро выдадим игроку с ником OKStyle 100 единиц брони.

 

Как вы видите, MAX_PLAYERS вообще отсутствует.

 

Часть 2. Имя игрока

До этого момента некоторые из вас могли знать только о двух вариантах получения имени игрока:

 

а) Каждый раз функцией GetPlayerName, вида:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

, где приходилось каждый раз создавать переменную.

 

б) Каждый раз функцией GetPlayerNameEx (например), вида:

, которая возвращала string с именем игрока с указанным id.

 

Сейчас я расскажу о небольшом "трике", который позволит быстро обращаться к имени заданного игрока.

 

В ваш enum с данными игрока нужно внести переменную:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

В OnPlayerConnect:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

И всё! Теперь в любом месте кода вы можете использовать эту переменную. Например:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Как вариант, вы можете использовать PVar'ы, но в этом случае вам всегда нужно будет создавать переменную для извлечения данных и PVar'а. Так что этот вариант - не вариант. Однако запомните, что PVar'ами, созданными в моде, можно оперировать в ФС, без их объявления, и наоборот - созданными PVar'ами из ФС можно оперировать в моде (например, в фс в PVar записывается имя, в моде можно извлекать из PVar'а имя).

 

Часть 3. Public vs Stock

Тут всё просто. Для public-функции нужен форвардинг (forward) и служит она для использования в таймерах или в Call*-образных функциях (CallLocal..., CallRemote...). Stock служит для вне'Call'овых и внетаймерных функций. Не использованный в коде stock компилятор не записывает в amx, в этом случае я просто рекомендую удалять stock'и, которые в моде не используются, чтобы не засорять сорсы.

 

Могу порекомендовать такой макрос, который позволяет не форвардить функции:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Использовать (например):

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Часть 4. Условие перебора

Я думаю, что уже все поняли, что switch куда быстрее, чем if/else if, а if/else if быстрее, чем if/if.

 

Давайте разберем OnDialogResponse на примере:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Важно: не забывайте после последнего case дописывать:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Полезно: в case можно использовать несколько значений сразу, если них существуют одинаковые действия:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Немного об inputtext. Будет полезно и для команд (в OnPlayerCommandText - cmdtext):

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

И запомните главное: ставить задефайненную константу или цифру - дело ваше, в игре это никак не отразится, т.к. компилятор при компилировании ставит цифру в тех местах, где вы использовали обозначенную константу. Обычно константы создают для удобства программера.

 

Автор: OKStyle 

pawno-crmp.ru

Оптимизация команд - Изучаем язык pawn

Оптимизации игровых модов.

Ну во-первых заставляет немного подгрузиться серверу система сохранения аккаунтов MxINI. Из этой системы можно сделать конфетку если постараться над инклюдом. НО, лучше не заморачиваться над багами данной системы и перейти на MySQL. Как перейти на MySQL найдете в гугле (Лучше переходите на R7, т.к. там наблюдается многопоточность.)Во-вторых это использование стандартной системы комманд. Да, strcmd вполне хорошая система, багов нету, но тот-же ZCMD, а темболее YCMD намного оптимизированней. Переход с одного на другое не составит труда, разве размеры и около дня для переписания комманд

Было:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Стало:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

1. Комманды станут короче.

2. Более оптимизированы.

3. Некоторые на убой не хотят использовать свич, хотя он намного удобнее сравнения.

4. Это много ненужных комманд/скриптов.

 

Пример:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

и т.д.со свичем

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Чем же это оптимизирует? А тем, что при сравнении сервер тоже использует память, и в итоге если этих диалогов будет не 2 как в примере, а 20000. То при поиске диалога сервер просто-напросто повиснет, а в случае со свичем он просто ищет диалог. То-есть он не проверяет каждую возможность, а просто берет число и ищет кейс с ним.Многие непопулярные сервера не задумываются о том, что например комманда /kiss, /minet и другие ненужные могут просто напросто положить сервер, особенно если эти комманды на strcmd с системой сохранения комманд MxINI. Эти комманды не то что просто валяются без дела, они еще и вредят ему. (Тот-же пример с /cnn, /cnnn, одну комманду можно смело убрать. Т.к. они выполняют одну и ту-же функцию но одна показывает ник, а другая нет...) А тем более меня поражают такие сервера, на которых стоят разнообразные казино, у людей денег море... Зачем казино? Господи, оно не вливается в ваш супер-пупер Role Play режим, где бомж приезжает и можно сказать находит чемодан с миллионами вирт. А ведь эти казино еще и нагружают сервер своими системами.В-пятых, это множество домов/квартир и других вещей. Ну вот у вас онлайн на сервере 20-30 человек. Зачем вам 600-700 домов? Куда они вам? Зачем вам 2000 квартир которые вы старательно выставляли? Зачем вам 40 бизнесов по всему штату? Зачем вам 33 организации на сервер? Когда 5-6 человек обычно администраторы, а остальные лидеры. Советую пока онлайн сервера не подрастет заставить игроков посидеть в одном городе... В-шестых, это огромное кол-во объектов, ненужных автомобилей на сервере. Где вы видели у мэрии около 120-150 объектов? Да и море автомобилей для фракции с максимальным кол-вом человек в 5-10 во фракции, из которых одновременно играет человека 2-3.В общем так, повышают пинг игроков огромное кол-во объектов, автомобилей, пикапов домов, пикапов квартир, великое кол-во ненужных комманд и систем... Так-же повышают пинг игроков многие другие системы (комманды, сохранение/загрузка аккаунтов).

 

Автор: Неизвестен.

pawno-crmp.ru

Оптимизация | Индивидуальные таймеры - Готовые решения

Добрый день. 

В этом уроке я хочу донести до вас довольно значимый способ оптимизации мода, который известен далеко не всем. Но сразу предупреждаю, если вы очень слабый скриптер, не читайте дальше и не пишите ничего в этой теме.Итак, таймеры. Многие считают что использовать кучу таймеров в моде - ужасно плохо, но это не так, если использовать их разумно. Нагружают сервер действия, срабатываемые в таймере, а не сами таймеры (совсем немного). Поэтому 1000 разумно сделанных таймеров будут полезнее чем 5 кое-как сделанных. Если вы это понимаете - идём дальше, иначе закрывайте тему.

Почти в каждом моде есть таймер, допустим на 1 секунду. В этом таймере есть цикл на всех игроков сервера, где с ними производятся действия. Например:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

Именно из за таких таймеров серверы с большим онлайном начинают испытывать лаги и ищут более мощный хостинг. Всё дело в том, что одно срабатывание из foreach (для одного игрока) проходит например за 0.25 - 1 мс (в зависимости от оптимизации и мощности процессора), что впрочем то не так уж и страшно. Но когда игроков 200, выполнение таймера занимает уже от 50 мс до 200 мс каждую секунду и пока весь таймер не закончит своё действие, сервер своими делами не займётся (синхронизация игроков и т.п.), поэтому в эти 200 мс сервер тупо висит - вот она причина лагов. Теперь давайте разберём как избавиться от этого и не мешать серверу заниматься необходимыми для работы сервера делами.

 

1) Убрать из ВСЕХ таймеров такие циклы с игроками. 

2) Объявить глобальный массив (ко всем new):

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

3) Ко всем forward:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

4) В OnPlayerConnect:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

5) В OnPlayerDisconnect:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

6) В конце мода:

Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.

В итоге мы получим индивидуальный таймер для каждого игрока, да, их будет 1000 при максимальном онлайне, но ничего страшного - серверу только лучше. Теперь все действия с игроком нужно использовать в PlayerUpdate (он срабатывает каждые 250 мс). Отдельные таймеры на 1 сек и т.п. создавать не нужно, просто подсчитывайте количество срабатываний PlayerUpdate (1 сек = 4 срабатывания) и выполняйте нужные действия.

И что же нам это всё даст? Когда сервер выполнял цикл, он выполнял его полностью на всех игроков и пока не закончил - другими делами не занимался. В нашем случае для каждого игрока идут отдельные таймеры, срабатывающие в разное время, а не сразу все. Поэтому между срабатываниями таймеров, пусть оно будет даже 0,01 мс, но сервер в это время займётся своими делами и ему хватит этого времени, а значит сервер не будет останавливаться в ожидании.

На этом всё, надеюсь что объяснил достаточно понятно. Удачного скриптинга!

 

Автор: XemyL

Сообщение отредактировал ac1nve: 15 Июнь 2017 - 21:42

pawno-crmp.ru


Prostoy-Site | Все права защищены © 2018 | Карта сайта