Автор: serfreeman1337
Первоисточник: Вы должны зарегистрироваться, чтобы видеть ссылки.
Иногда перед нами появляется задача узнать индексы нужных нам игроков. Правильнее всего это сделать при помощи функции Вы должны зарегистрироваться, чтобы видеть ссылки., но чаще всего в плагинах можно заметить цикл от 1-ого до 32-ух с проверкой индекса при помощи нативов AMXX. Такой метод называется loop или "петля". Применять его в плагинах никак неправильно. И вот почему. Это вопрос оптимизации, основное правило которого звучит так:
Разберем пример с получением индексов всех живых игроков. Код у нас будет таким:
Теперь подсчитаем кол-во обращения к функциям AMXX и какое время потребовалось на выполнение кода. В этом нам поможет сборка AMXX для профилирования плагинов - Вы должны зарегистрироваться, чтобы видеть ссылки.. Версия старая, но рабочая
Код выполнился за 0.000011 секунд. К функциям обращались 33 раза. А теперь сравним это с get_players. Код такой:
Данные профилирования:
Наш код выполнился за 0.000002 секунд. Обращение к функциям AMXX было всего однажды. Для наглядности, давайте проведем стресс-тест, выполним эти блоки кода 1000 раз. Код будет такой:
Результаты:
get_players - 0.000320. loop - 0.009689. Существенная разница, не так ли? Правильный метод быстрее быдлокодого в 30 раз. Ответ очевиден, использование метода loop – признак плохого кода и неопытности автора, ну, или лени :p
=============================================================================================
Полезный комментарий к статье с первоисточника:
Первоисточник: Вы должны зарегистрироваться, чтобы видеть ссылки.
Иногда перед нами появляется задача узнать индексы нужных нам игроков. Правильнее всего это сделать при помощи функции Вы должны зарегистрироваться, чтобы видеть ссылки., но чаще всего в плагинах можно заметить цикл от 1-ого до 32-ух с проверкой индекса при помощи нативов AMXX. Такой метод называется loop или "петля". Применять его в плагинах никак неправильно. И вот почему. Это вопрос оптимизации, основное правило которого звучит так:
Чем меньше вызовов функций, тем лучше.
Разберем пример с получением индексов всех живых игроков. Код у нас будет таким:
- Код: Выделить всё
public function(){ // метод loop
new pnum = get_playersnum()
for(new player = 1 ; player <= pnum ; player++){
if(!is_user_alive(player))
continue
// ...
}
}
Теперь подсчитаем кол-во обращения к функциям AMXX и какое время потребовалось на выполнение кода. В этом нам поможет сборка AMXX для профилирования плагинов - Вы должны зарегистрироваться, чтобы видеть ссылки.. Версия старая, но рабочая
- Код: Выделить всё
date: Sun Aug 10 08:42:44 2014 map: de_inferno // профилирование loop
type | name | calls | time / min / max
-------------------------------------------------------------------
n | register_plugin | 1 | 0.000001 / 0.000001 / 0.000001
n | register_srvcmd | 1 | 0.000022 / 0.000022 / 0.000022
n | get_maxplayers | 1 | 0.000001 / 0.000001 / 0.000001
n | is_user_alive | 32 | 0.000012 / 0.000000 / 0.000001
p | function | 1 | 0.000011 / 0.000011 / 0.000011
p | plugin_init | 1 | 0.000001 / 0.000001 / 0.000001
0 natives, 0 public callbacks, 2 function calls were not executed.
Код выполнился за 0.000011 секунд. К функциям обращались 33 раза. А теперь сравним это с get_players. Код такой:
- Код: Выделить всё
public function(){ // get_players
new players[32],pnum
get_players(players,pnum,"a")
for(new i,player ; i < pnum ; i++){
player = players[i]
// ..
}
}
Данные профилирования:
- Код: Выделить всё
date: Sun Aug 10 08:48:37 2014 map: de_inferno // профилирование get_players
type | name | calls | time / min / max
-------------------------------------------------------------------
n | register_plugin | 1 | 0.000002 / 0.000002 / 0.000002
n | register_srvcmd | 1 | 0.000022 / 0.000022 / 0.000022
n | get_players | 1 | 0.000003 / 0.000003 / 0.000003
p | function | 1 | 0.000002 / 0.000002 / 0.000002
p | plugin_init | 1 | 0.000001 / 0.000001 / 0.000001
0 natives, 0 public callbacks, 2 function calls were not executed.
Наш код выполнился за 0.000002 секунд. Обращение к функциям AMXX было всего однажды. Для наглядности, давайте проведем стресс-тест, выполним эти блоки кода 1000 раз. Код будет такой:
- Код: Выделить всё
public plugin_init() { // сравнение методов
register_plugin(PLUGIN, VERSION, AUTHOR)
register_srvcmd("test5","functionLoop")
register_srvcmd("test6","functionPlayers")
}
public functionLoop(){
new s
while(s++ < 1000){
new pnum = get_maxplayers()
for(new player = 1 ; player <= pnum ; player ++){
if(!is_user_alive(player))
continue
// ...
}
}
}
public functionPlayers(){
new s
while(s++ < 1000){
new players[32],pnum
get_players(players,pnum,"a")
for(new i,player ; i < pnum ; i++){
player = players[i]
// ..
}
}
}
Результаты:
- Код: Выделить всё
date: Sun Aug 10 08:55:26 2014 map: de_inferno // данные сравнения
type | name | calls | time / min / max
-------------------------------------------------------------------
n | register_plugin | 1 | 0.000002 / 0.000002 / 0.000002
n | register_srvcmd | 2 | 0.000041 / 0.000020 / 0.000022
n | get_maxplayers | 1000 | 0.000280 / 0.000000 / 0.000001
n | is_user_alive | 32000 | 0.009030 / 0.000000 / 0.000090
n | get_players | 1000 | 0.000369 / 0.000000 / 0.000002
p | functionLoop | 1 | 0.009689 / 0.009689 / 0.009689
p | functionPlayers | 1 | 0.000320 / 0.000320 / 0.000320
p | plugin_init | 1 | 0.000002 / 0.000002 / 0.000002
0 natives, 0 public callbacks, 3 function calls were not executed.
get_players - 0.000320. loop - 0.009689. Существенная разница, не так ли? Правильный метод быстрее быдлокодого в 30 раз. Ответ очевиден, использование метода loop – признак плохого кода и неопытности автора, ну, или лени :p
=============================================================================================
Полезный комментарий к статье с первоисточника:
Radius писал(а):Попробуйте прогнать вот эти оптимизированные варианты. Даже с оптимизацией loop выигрывает в 3 раза. На моем процессоре результат 10 секунд loop и 34 секунды get_players.
- Код: Выделить всё
functionLoop()
{
static time;
time = get_systime();
new s, pnum = get_maxplayers()
while(s++ < cellmax/100){
for(new player = 1 ; player <= pnum ; player++){
if (is_user_alive(player)) {
}
}
}
server_print("%d sec", get_systime() - time);
}
functionPlayers()
{
static time;
time = get_systime();
new s, players[32], pnum, player
while(s++ < cellmax/100){
get_players(players,pnum,"a")
for(new i; i < pnum ; i++){
player = players[i]
}
}
server_print("%d sec", get_systime() - time);
}