Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Страница 1 из 4 1 2 3 ... ПоследняяПоследняя
Показано с 1 по 10 из 34
  1. #1
    Аватар для XemyL
    Пользователь

    Статус
    Оффлайн
    Регистрация
    30.11.2013
    Сообщений
    22
    Репутация:
    25 ±

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

    Добрый день, пользователи Pro-Pawn.

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

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


    PHP код:
    public Timer1Second()
    {
        foreach(...)
        {
            
    // Действия
        
    }
        return 
    1;

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

    1) Убрать из ВСЕХ таймеров такие циклы с игроками.
    2) Объявить глобальный массив (ко всем new):

    PHP код:
    new PlayerTimerID[MAX_PLAYERS]; 
    3) Ко всем forward:
    PHP код:
    forward PlayerUpdate(playerid); 
    4) В OnPlayerConnect:
    PHP код:
    PlayerTimerID[playerid] = SetTimerEx("PlayerUpdate"2501"d"playerid); 
    5) В OnPlayerDisconnect:
    PHP код:
    KillTimer(PlayerTimerID[playerid]); 
    6) В конце мода:
    PHP код:
    public PlayerUpdate(playerid)
    {
        return 
    1;

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

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

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

  2. 9 пользователя(ей) сказали cпасибо:
    #ball (03.08.2014) Albert (29.01.2015) Exclusive (16.04.2014) HAV (16.03.2017) Jeff_Monson (12.04.2014) KShaddix (15.04.2014) MaKcuM (12.01.2017) RefunQ (04.06.2016) Копюшон (04.05.2014)
  3. #2
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    А не проще ли 1 глобальный таймер в 500 мс + деление MAX_PLAYERS на несколько тактов (например: сначала обрабатываем чётные ID, а потом - нечётные)? Если всё эти подкрепить системой, которая используется в foreach (чтоб цикл пробегался только по тем игрокам, кто онлайн), выйдет 1 таймер и не такая уж и большая нагрузка. Да и не обязательно делить только на чётные и нечётные. Можно и на большие куски разделить всех игроков. Выйдет, по моему, гораздо удобнее.
    Хотя и этот способ хороший. Но пока оба способа не будут проверены на реальном сервере с онлайном хотя бы в 500 человек, говорить что-то о том, какой из них лучше, не стоит, как я считаю :)
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  4. #3
    Аватар для XemyL
    Пользователь

    Статус
    Оффлайн
    Регистрация
    30.11.2013
    Сообщений
    22
    Репутация:
    25 ±
    Цитата Сообщение от DeimoS Посмотреть сообщение
    А не проще ли 1 глобальный таймер в 500 мс + деление MAX_PLAYERS на несколько тактов (например: сначала обрабатываем чётные ID, а потом - нечётные)? Если всё эти подкрепить системой, которая используется в foreach (чтоб цикл пробегался только по тем игрокам, кто онлайн), выйдет 1 таймер и не такая уж и большая нагрузка. Да и не обязательно делить только на чётные и нечётные. Можно и на большие куски разделить всех игроков. Выйдет, по моему, гораздо удобнее.
    Хотя и этот способ хороший. Но пока оба способа не будут проверены на реальном сервере с онлайном хотя бы в 500 человек, говорить что-то о том, какой из них лучше, не стоит, как я считаю :)
    А я считаю что мой способ наоборот удобнее. Метод был протестирован на сервере с онлайном 300 человек. У них тогда ещё были огромные лаги, а после того как я им перевёл на такие таймеры, все лаги прошли. Но онлайн они больше 300 не набрали, увы...

  5. Пользователь сказал cпасибо:
    Jeff_Monson (12.04.2014)
  6. #4
    Аватар для Jeff_Monson
    Пользователь

    Статус
    Оффлайн
    Регистрация
    20.10.2013
    Сообщений
    40
    Репутация:
    1 ±
    Реально удобно, сам так пользуюсь с того момента как вы создали в другом портале тему.

    Вот вопрос а проверки античиты, и прочие туда в пихать или лучше в глобальный?

    В глобальном у меня только gzcheck и mzcheck античиты в индивидуальном таймере.

  7. #5
    Аватар для XemyL
    Пользователь

    Статус
    Оффлайн
    Регистрация
    30.11.2013
    Сообщений
    22
    Репутация:
    25 ±
    Цитата Сообщение от Jeff_Monson Посмотреть сообщение
    Реально удобно, сам так пользуюсь с того момента как вы создали в другом портале тему.

    Вот вопрос а проверки античиты, и прочие туда в пихать или лучше в глобальный?

    В глобальном у меня только gzcheck и mzcheck античиты в индивидуальном таймере.
    Античиты тоже в индивидуальные.

  8. Пользователь сказал cпасибо:
    Albert (29.01.2015)
  9. #6
    Аватар для KShaddix
    Пользователь

    Статус
    Оффлайн
    Регистрация
    07.02.2014
    Сообщений
    39
    Репутация:
    5 ±
    Раньше я видел лишь утверждения, что таймеров должно быть не больше 10. В противном случае на сервере будут лаги. lol.
    Доверюсь тебе, сделаю по твоему способу.

  10. #7
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от KShaddix Посмотреть сообщение
    Раньше я видел лишь утверждения, что таймеров должно быть не больше 10. В противном случае на сервере будут лаги. lol.
    Доверюсь тебе, сделаю по твоему способу.
    ...
    Цитата Сообщение от DeimoS Посмотреть сообщение
    Нагрузку даёт функция, вызываемая таймером. Сам же таймер является своеобразной временной меткой, по которой мод вызывает ту или иную функцию. Он лишь записывается в память сервера, но никак не нагружает ЦП. Проверить это легко. Вставляем в new.pwn
    PHP код:
    new Timer;
    for(new 
    i5000; ++iTimer SetTimer("_"1000true);
    printf("Таймеров запущено - %d",Timer); 
    и запускаем сервер. Открываем диспетчер задач, ищем процесс сервера (samp-server.exe) и делаем скрин. Ну и смотрим на то, как нагружает сервер ЦП/заходим на сервер в ожидании лагов.
    После закрываем его, открываем мод и убираем цикл с созданием таймера. Вновь запускаем сервер и сверяем данные со скрина с данными в диспетчере задач.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  11. Пользователь сказал cпасибо:
    KShaddix (15.04.2014)
  12. #8
    Аватар для KShaddix
    Пользователь

    Статус
    Оффлайн
    Регистрация
    07.02.2014
    Сообщений
    39
    Репутация:
    5 ±
    Цитата Сообщение от Tracer Посмотреть сообщение
    Сам таймер не вызывает лаги.Даже SetTimerEx,просто нужно умно их использовать.
    Я уже понял, прочитав верхний пост. Сейчас имею в виду, что раньше был убеждён в обратном.

  13. #9
    Аватар для Kenny_Dalglish
    Заблокирован

    Статус
    Оффлайн
    Регистрация
    24.02.2014
    Сообщений
    179
    Репутация:
    -1 ±
    Урок то хороший вот только не понял как создавать таймеры на 1-10 секунд. Пример покажите...

  14. #10
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Эмм
    PHP код:
    SetTimerEx("PlayerUpdate"1000*101"d"playerid); 
    таймер на 10 секунд, не?
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  15. 3 пользователя(ей) сказали cпасибо:
    #enotya (29.03.2017) Albert (29.01.2015) Salvacore (05.05.2014)
 

 
Страница 1 из 4 1 2 3 ... ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •