Оптимизация циклов MAX_PLAYERS
#21

GetMaxPlayers() лучше любого foreach, т.к. зачастую надо прогонять все доступные слоты и инициализировать в них переменные, поэтому лучше всего просто устанавливать максимальное кол-во слотов для игроков примерно столько, сколько в среднем у вас играет или может играть в среднем.
Если слотов мало, то в конфиге увеличивается кол-во и делается рестарт. От рестарта ещё ни кто не умер.

В создании динамических массивов вижу смысл только для застрименых тачек, чтобы не гонять цыклы от 1 до 2000, т.к. в сампе нету ф-ии определения загруженных на данный момент общего кол-ва тачек (типа GetMaxVehicles() ).

МОжно попытаться типа так

pawn Code:
stock GetHighestVehicleID()
{
    for(new vid = 1; vid < (MAX_VEHICLES-1); vid++)
    {
        if( GetVehicleModel(vid) == 0 &&
            GetVehicleModel(vid+1) == 0 &&
            GetVehicleModel(vid+2) == 0)
        {
            return vid;
        }
    }
    return 0;
}
но при системе владения авто, которая удаляет тачки после их смерти, образуются большие дыры. По-этому этот способ тоже не из лучших.

Лучше писать самому что то на подобие

pawn Code:
public OnVehicleStreamIn(vehicleid, forplayerid)
{   //Вызывается при появлении тачки vehicleid в поле зрения игрока forplayerid.
    Itter_Add(StreamedVehicle[forplayerid], vehicleid); // Добавляем в динамическии цикл новую итерацию для этого игрока.
...
При использовании foreach у меня сервер зависает, что типа работает но ни одно команда, даже через удалённую консоль, не отрабатывается. Т.е. приходится ФСом крашить сервер.
Reply
#22

Quote:
Originally Posted by MX_Master
View Post
мои 5 копеек, мобыть кому-то понравится

[php]stock playerMaxID = 0;

public OnPlayerConnect ( playerid )
{
if ( playerid > playerMaxID ) playerMaxID = playerid;
}

public OnPlayerDisconnect ( playerid, reason )
{
if ( playerid <= playerMaxID )
{
for ( new i = playerid - 1; i >= 0; --i )
{
if ( IsPlayerConnected(i) )
{
playerMaxID = i;
break;
}
}
}
}
Code:
public OnPlayerConnect ( playerid ) 
{
    if ( playerid > playerMaxID ) playerMaxID = playerid;
}
тут всё понятно. ошибки быть не должно.

Смотрим тут
Code:
public OnPlayerDisconnect ( playerid, reason )
{
    if ( playerid <= playerMaxID )
    {
        for ( new i = playerid - 1; i >= 0; --i )
        {
            if ( IsPlayerConnected(i) )
            {
                playerMaxID = i;
                break;
            }
        }
    }
}
тут если на сервере 120 человек (playerMaxID = 120) и мой ид 99. Я вышел из игры.
То подставив в цыкл 99, новый максимальный Ид определится как 98, т.к. 98 игрок на сервере. Хотя наш максимальный реальный ИД останется как был 120. Лажа.

Или я не прав?
Code:
if ( 99 <= 120 )
{
        for ( new i = 99 - 1; i >= 0; --i )
        {
            if ( IsPlayerConnected(98) )
            {
                playerMaxID = 98;
                break;
            }
        }
}
А вот код автора темы
Code:
for(new i=0;i<MaxPlayers;i++)
{
    if(PLIDs[i] == playerid)
    {
        MaxPlayers--;
        PLIDs[i] = PLIDs[MaxPlayers];
        PLIDs[MaxPlayers] = -1;
        break;
    }
}
Сделаем подстановку
Code:
for(new i=0;i<120;i++)
{
    if(PLIDs[99] == 99)/допустим дыр не было и я в 99 ячейки массива, т.е. i = 99
    {
        MaxPlayers--;//120-1=119
        PLIDs[i] = PLIDs[MaxPlayers];//PLIDs[99] = PLIDs[119];
        PLIDs[MaxPlayers] = -1;//PLIDs[119] = -1;
        break;
    }
}
т.е. мы освободили ячейку 119, закрыв глаза на то что есть ещё 20 ячеек после 99 до 120. С ними что?
а в 99 записали максимальный ИД который был в 119 ячейке.
Но это не верно.

Что скажете на это авторы? Или у меня крыша поехала и я не вижу элементарного или Вы пишите чушь.
Теория и практика у вас совсем не сходится, т.к. то, что написано работает как бы только на первый взгляд, в практике это работать не будет. Хватит писать коды не проверенные на практике.
Reply
#23

Замутил тестик всех способов создания циклов "MAX_PLAYERS" с использованием OnPlayerConnect и OnPlayerDisconnect(ведь тики на них тоже тратятся).
Код тут: http://pastebin.com/JUCRZDDY
Результаты:
Code:
IsPlayerConnected: 509
GetMaxPlayers: 503
GetPlayerLastID: 591 (мною модифицированный способ от Alex009)
PLID: 187 (предложенный вариант в этой теме)
foreach: 246 (foreach от ******'a)
foreach_step: 647 (foreach который опубликовал степашка тут)

Дальше я подумал кол-во подключений/отключений привести к более реальному количеству.
Код тут: http://pastebin.com/VP6CR7fv
Результаты:
Code:
IsPlayerConnected: 503
GetMaxPlayers: 450
GetPlayerLastID: 1062 (мною модифицированный способ от Alex009)
PLID: 134 (предложенный вариант в этой теме)
foreach: 141 (foreach от ******'a)
foreach_step: 144 (foreach который опубликовал степашка тут)
Тут результаты куда более приятнее. Забавно, что способ с GetPlayerLastID стал работать в 2 раза медленнее.
upd: обновил, спасибо за замечания.
Reply
#24

Quote:
Originally Posted by ZiGGi
View Post
Замутил тестик всех способов создания циклов "MAX_PLAYERS" с использованием OnPlayerConnect и OnPlayerDisconnect(ведь тики на них тоже тратятся).
Код тут: http://pastebin.com/JUCRZDDY
Результаты:
Code:
IsPlayerConnected: 503
GetMaxPlayers: 500
GetPlayerLastID: 118 (мною модифицированный способ от Alex009)
PLID: 172 (предложенный вариант в этой теме)
foreach: 254 (foreach от ******'a)
foreach_step: 556 (foreach который опубликовал степашка тут)
Если увеличить PLAYER_CONNECTING и PLAYER_DISCONNECTING, то оба foreach(при чём степашкин гораздо больше) и PLIDs будут сильно увеличивать своё время выполнения, когда остальные способы гораздо меньше.


Дальше я подумал кол-во подключений/отключений привести к более реальному количеству.
Код тут: http://pastebin.com/VP6CR7fv
Результаты:
Code:
IsPlayerConnected: 446
GetMaxPlayers: 461
GetPlayerLastID: 111 (мною модифицированный способ от Alex009)
PLID: 128 (предложенный вариант в этой теме)
foreach: 138 (foreach от ******'a)
foreach_step: 141 (foreach который опубликовал степашка тут)
Тут результаты куда более приятнее. При увеличении PLAYER_CONNECTING и PLAYER_DISCONNECTING различия в значениях разрываются меньше, но и тут способ GetPlayerLastID работает быстрее, при любых параметрах, всегда...
players_lastID тупо самый большой ид игрока хранит, а не список только подключенных. Если допустим на сервере будет 5 игроков, ид 1, 4, 200, 500, ему все равно 500 интераций сделать придется
Reply
#25

Quote:
Originally Posted by ZiGGi
View Post
Замутил тестик всех способов создания циклов "MAX_PLAYERS" с использованием OnPlayerConnect и OnPlayerDisconnect(ведь тики на них тоже тратятся).
Код тут: http://pastebin.com/JUCRZDDY
Результаты:
Code:
IsPlayerConnected: 503
GetMaxPlayers: 500
GetPlayerLastID: 118 (мною модифицированный способ от Alex009)
PLID: 172 (предложенный вариант в этой теме)
foreach: 254 (foreach от ******'a)
foreach_step: 556 (foreach который опубликовал степашка тут)
Если увеличить PLAYER_CONNECTING и PLAYER_DISCONNECTING, то оба foreach(при чём степашкин гораздо больше) и PLIDs будут сильно увеличивать своё время выполнения, когда остальные способы гораздо меньше.


Дальше я подумал кол-во подключений/отключений привести к более реальному количеству.
Код тут: http://pastebin.com/VP6CR7fv
Результаты:
Code:
IsPlayerConnected: 446
GetMaxPlayers: 461
GetPlayerLastID: 111 (мною модифицированный способ от Alex009)
PLID: 128 (предложенный вариант в этой теме)
foreach: 138 (foreach от ******'a)
foreach_step: 141 (foreach который опубликовал степашка тут)
Тут результаты куда более приятнее. При увеличении PLAYER_CONNECTING и PLAYER_DISCONNECTING различия в значениях разрываются меньше, но и тут способ GetPlayerLastID работает быстрее, при любых параметрах, всегда...
с моим цыклом ты тоже ошибся: ты вызывал дефолтное событие, которое по мимо моего кода ещё и вызывало всю свою внутреннюю портянку, измени имя вызываемого колбека чтобы замерить скорость только моего кода.

Code:
[23:53:13] IsPlayerConnected: 341
[23:53:13] GetMaxPlayers: 51
[23:53:13] GetPlayerLastID: 68
[23:53:13] PLID: 133
[23:53:13] foreach: 198
[23:53:14] foreach_step: 376

[23:53:22] IsPlayerConnected: 360
[23:53:22] GetMaxPlayers: 53
[23:53:23] GetPlayerLastID: 68
[23:53:23] PLID: 133
[23:53:23] foreach: 198
[23:53:23] foreach_step: 359
Reply
#26

И второй вариант кода:
Code:
[23:56:00] IsPlayerConnected: 305
[23:56:00] GetMaxPlayers: 7
[23:56:00] GetPlayerLastID: 82
[23:56:00] PLID: 99
[23:56:01] foreach: 87
[23:56:01] foreach_step: 88

[23:56:04] IsPlayerConnected: 306
[23:56:04] GetMaxPlayers: 7
[23:56:04] GetPlayerLastID: 65
[23:56:04] PLID: 88
[23:56:04] foreach: 101
[23:56:04] foreach_step: 119

[23:56:07] IsPlayerConnected: 334
[23:56:07] GetMaxPlayers: 7
[23:56:07] GetPlayerLastID: 65
[23:56:07] PLID: 117
[23:56:07] foreach: 121
[23:56:07] foreach_step: 104
ЗЫ у тебя что за система, почему у меня так числа отличаются
ЗЫЫ GetMaxPlayers дак вобще на 2 порядка отличия
Reply
#27

Quote:
Originally Posted by Stepashka
View Post
ЗЫ у тебя что за система, почему у меня так числа отличаются
ЗЫЫ GetMaxPlayers дак вобще на 2 порядка отличия
Великий и могучий Intel Pentium 4, правда, в своё время
Спасибо за замечания, сейчас подогнал код к более реальной картине(теперь иды подключающихся умножаются на 10). Собственно я делаю выбор за foreach улесса - быстро, удобно, функционально.
Reply
#28

Quote:
Originally Posted by ZiGGi
View Post
Великий и могучий Intel Pentium 4, правда, в своё время
Спасибо за замечания, сейчас подогнал код к более реальной картине(теперь иды подключающихся умножаются на 10). Собственно я делаю выбор за foreach улесса - быстро, удобно, функционально.
надо будет на работе проверить на i5
Reply
#29

кстати у меня тоже не настолько и современная машина дома:
Quote:

AMD Athlon™ 64 X2 Dual Core Processor 4200+
Частота ЦП 2529.8 MHz (исходная: 2200 MHz, overclock: 15%)

может такие существенные отличия из-за архитектурных отличий амд и интел
Reply
#30

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

И насколько я понял, самый быстрый способ это способ, который скриптер сам может придумать на скорую руку. Вот это для него и называется быстро.
Reply
#31

Quote:
Originally Posted by HappyScripter
View Post
Я думаю, что эти быстрые способы так и останутся в узком кругу скриптеров, а остальное подавляющие большинство начинающих и не очень скриптеров будет использовать старый добрый перебор всех ячеек с проверкой на коннект стандартной функцией. И причина тут одна, нет тут такой темы, где бы в самом первом посте был дан аргументированный список стандартных быстрых конструкций для улучшения производительности сервера. Причем, с вот этими наглядными цифрами из тестов и списком опытных скриптеров, который согласны с тем, что это самый лучший вариант. А по коварным закоулкам тем форума, с непонятными для новичков названиями, никто ходить не будет.

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

Кстати только сейчас понял что GetMaxPlayers, вообще необъективна в данных тестах, для её проверки нужно использовать или ботов ии настоящих игроков.
Reply
#32

Quote:
Originally Posted by Stepashka
View Post
кто мешает сделать красиво оформленную тему со всей этой поезной информацией, или хватает только на то что бы закинуть камень в огород и дальше ныкать все по темам?!
Давайте лучше обсудим это в нужной теме, которая кстати уже почти точно смотрится архивом - http://forum.sa-mp.com/showthread.ph...11#post1383711
Reply
#33

Quote:
Originally Posted by HappyScripter
View Post
Давайте лучше обсудим это в нужной теме, которая кстати уже почти точно смотрится архивом - http://forum.sa-mp.com/showthread.ph...11#post1383711
а нечего обсуждать, я тут не для развития сижу, а для порядка.
Не хочешь учавствовать в развитии - нечего других в это тыкать.
Reply
#34

Quote:
Originally Posted by ZiGGi
View Post
Великий и могучий Intel Pentium 4, правда, в своё время
Спасибо за замечания, сейчас подогнал код к более реальной картине(теперь иды подключающихся умножаются на 10). Собственно я делаю выбор за foreach улесса - быстро, удобно, функционально.
проверил код на работе.

Одно замечание: при использовании foreach как моего так и улесса не надо использовать
pawn Code:
if(!IsPlayerConnected(i) || IsPlayerNPC(i))
потому что в массивах итак лежат ИД только игроков и только тех кто онлайн.
Да признаюсь что в приведенном мной примере нет исключения ботов, просто я их не использую, поэтому и не включал, но это 1 дополнительное условие при коннетке.

Если исключить эти лишние проверки скорость обоих foreach увеличивается почти на 70% и они выполняются за одинаковое время:
Code:
[14:30:25] IsPlayerConnected: 124
[14:30:25] GetMaxPlayers: 18
[14:30:26] GetPlayerLastID: 305
[14:30:26] PLID: 24
[14:30:26] foreach: 12
[14:30:26] foreach_step: 13

[14:30:28] IsPlayerConnected: 128
[14:30:28] GetMaxPlayers: 21
[14:30:28] GetPlayerLastID: 324
[14:30:28] PLID: 28
[14:30:28] foreach: 12
[14:30:28] foreach_step: 12


[14:30:31] IsPlayerConnected: 127
[14:30:31] GetMaxPlayers: 17
[14:30:31] GetPlayerLastID: 316
[14:30:31] PLID: 29
[14:30:31] foreach: 15
[14:30:31] foreach_step: 13

[14:30:33] IsPlayerConnected: 126
[14:30:33] GetMaxPlayers: 17
[14:30:34] GetPlayerLastID: 331
[14:30:34] PLID: 26
[14:30:34] foreach: 11
[14:30:34] foreach_step: 13

[14:30:36] IsPlayerConnected: 124
[14:30:36] GetMaxPlayers: 21
[14:30:36] GetPlayerLastID: 329
[14:30:36] PLID: 25
[14:30:36] foreach: 12
[14:30:36] foreach_step: 16

[14:30:38] IsPlayerConnected: 118
[14:30:38] GetMaxPlayers: 17
[14:30:39] GetPlayerLastID: 329
[14:30:39] PLID: 29
[14:30:39] foreach: 13
[14:30:39] foreach_step: 14
результаты на i5 650 3.2GhHz (4 ядра, 4Гб оперативки)
Reply
#35

Quote:
Originally Posted by Stepashka
View Post
проверил код на работе.

Одно замечание: при использовании foreach как моего так и улесса не надо использовать
pawn Code:
if(!IsPlayerConnected(i) || IsPlayerNPC(i))
потому что в массивах итак лежат ИД только игроков и только тех кто онлайн.
Да признаюсь что в приведенном мной примере нет исключения ботов, просто я их не использую, поэтому и не включал, но это 1 дополнительное условие при коннетке.

Если исключить эти лишние проверки скорость обоих foreach увеличивается почти на 70% и они выполняются за одинаковое время:

результаты на i5 650 3.2GhHz (4 ядра, 4Гб оперативки)
Да, это совсем вылетело из головы.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)