Оптимизация мода/скрипта. Оптимизация pawno
Оптимизация мода/скрипта - Изучаем язык pawn
Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Подумайте заранее, какая самая большая строка может использоваться в массиве, и максимально уменьшите число в квадратных скобках.Макс. знчение для SendClientMessage 144.Совет #4:Соблюдайте табуляцию/выравнивание кода (лесенка) и не используйте функций типо tabsize.Совет #5:В некоторых случаях лучше использовать функцию напрямую, чем заводить для неё переменную.Пример:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Лучше сделать так:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Совет #6:Если в переменной может быть значение только 0 или 1, используйте тип переменной bool.Пример:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Лучше записать так:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Совет #10:Если возможно, лучше использовать имя клавиши, нежели её код.Пример:Клавиша Alt: KEY_WALK/1024Лучше записать KEY_WALK.Совет #11:В большинстве случаев, использование паблика OnPlayerUpdate не оправдывает само себя, поэтому лучше с ним не злоупотреблятb.Совет #12:НИКОГДА не используйте цикл в цикле (последнее время частенько такое замечаю).Пример:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Совет #13:Если вы часто используете один и тот же код, лучше создать для него функцию.Пользуясь этими советами, вы добьётесь большей эффективности скриптинга. Как в быстродействии, так и в визуальном восприятии кода.А теперь пара приёмов "оптимизированного" кода.1. Структура switch:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
2. Часто в функциях/командах используется:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
"Функцию" return, можно использовать в составе с любой функцией которая возвращает 1 или 0 (истина или ложь).В нашем примере можно сделать так:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
2.1. Если функция возвращает true/else по условию:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Можно записать так:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
3. Использование псевдодинамических массивов для оптимизации циклов типа:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
==============================================================================================Оптимизация циклов вида:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Это конечно давало некоторый прирост, но я пошел еще дальше!Первой идеей было использовать функцию GetMaxPlayers(), но это никак не помогло бы: на сервере могут быть всего 3 игрока, ид которых 0, 7 и 28, и циклу приходилось бы совершать 28 тактов.К сожалению, в pawn нельзя создавать динамические массивы, поэтому я придумал использовать что-то вроде псевдодинамического массива для хранения идподключенных игроков. Создал глобальный масив:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Далее я ввел переменную содержащую количество игроков на сервере:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Теперь надо добавить в паблик OnPlayerConnect необходимые операции с глобальными переменными:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Все довольно просто - игрок подключается, и его ИД помещается в последнюю свободную ячейку массива PLIDs, ну а переменная MaxPlayers становится на единицу больше.С пабликом OnPlayerDisconnect все немного сложнее. Игрок выходит, тоесть слот в PLIDs который занимала его ИД надо очистить. Но мне не нужен пустой слот, поэтому я присваиваю ему значение самого последнего слота PLIDs, и вот последний уже очищаю:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
После оптимизации:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Плюсы данного метода:- отсутствуют лишние такты циклов- не требуется проверять подключен ли игрокМинусы:- меняется порядок ИД игроков при выполнении циклов==============================================================================================4. Использование массива вместо функции GetPlayerName (либо ее аналога, GetPlayerNameEx) для узнавания никнейма игрока.Для этого создаем глобальный двумерный массив:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Далее в OnPlayerConnect'e записываем никнейм игрока в массив:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Пример использование:Пожалуйста войдите или зарегистрируйтесь чтобы увидить ссылку.
Автор: eFFect aka YoYopawno-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