Просмотр полной версии : [CMD] /cc (ZCMD/DC_CMD)
Daniel_Cortez
02.09.2014, 18:16
Думаю, не нужно объяснять, что делает эта команда - она есть в 90% всех модов.
Для тех, кто думает, что обычный цикл for на 100 итераций никак не оптимизировать: вынужден вас огорчить...
В обычном виде на каждой итерации цикла функции SendClientMessageToAll передаются одни и те же параметры, поэтому с помощью #emit передача параметров вынесена за пределы цикла - в теле цикла оставлен только сам вызов функции.
И да, я смею называть это максимальной оптимизацией. Возможно, даже слишком.
CMD:cc(playerid, params[]) // by Daniel_Cortez \\ pro-pawn.ru
{
// проверка на админа (при необходимости замените на свою)
if(PlayerInfo[playerid][pAdmin] != 0)
{
// объявить строковую константу и счётчик цикла
static const str[] = "";
new i = 100;
// трюк, предотвращающий краш компилятора (баг sysreq.c)
// (баг исправлен в патчах от Zeex, в компиляторах версий 0x030A и новее
// обход бага не нужен, для чего и используется директива #if)
#if __Pawn < 0x030A
{ if(0 == i) SendClientMessageToAll(0, str); }
#endif
// передать параметры для SendClientMessageToAll
#emit push.c str
#emit push.c 0xFFFFFFFF
#emit push.c 8
// вызвать функцию 100 раз
do{
#emit sysreq.c SendClientMessageToAll
}while(--i);
// освободить стековое пространство, зарезервированное под параметры
#emit stack 12
}
return 1;
}
P.S.: Данная команда представляет собой всего лишь пример оптимизации с помощью #emit (в частности, пропуска передачи через стек одних и тех же аргументов функции при её многократном вызове). Этот приём, как и любой другой, связанный с #emit, имеет смысл только для оптимизации самых узких мест, влияющих на производительность сервера.
Автор: Daniel_Cortez (http://pro-pawn.ru/member.php?100-Daniel_Cortez)
Специально для Pro-Pawn.ru (http://www.pro-pawn.ru)
Копирование данной статьи на других ресурсах без разрешения автора запрещено!
Batka1337
03.03.2016, 23:20
Блин в комментах обосрали(((
https://pp.vk.me/c630620/v630620040/2aacb/pvDkFPmpTGE.jpg
middlematt
03.03.2016, 23:36
То чувство, когда ты только что прочитал эти комментарии и увидел их на портале.
Иван Бубнов
03.03.2016, 23:37
То чувство, когда ты только что прочитал эти комментарии и увидел их на портале.
link go
Блин в комментах обосрали(((
https://pp.vk.me/c630620/v630620040/2aacb/pvDkFPmpTGE.jpg
Но его код ведь меньше((
Daniel_Cortez
04.03.2016, 11:42
Я просто оставлю это здесь: http://pro-pawn.ru/showthread.php?12773
$continue$
04.03.2016, 16:22
Ну или:
https://pp.vk.me/c630023/v630023369/168ed/qd9CD29TmNc.jpg
DeadScripter
05.03.2016, 22:08
Я просто оставлю это здесь: http://pro-pawn.ru/showthread.php?12773
Твоими фактами кидаться в табло "Супыр скрыптырам" буду. И док-ва есть и пояснения. Вообще класс.
TheMallard
06.03.2016, 10:13
Так говоришь, будто жалобу на дудвансах пишешь.
И да, я смею называть это максимальной оптимизацией. Возможно, даже слишком.
new i = 100;
to
new i[1 char];
i{0} = 100;
:crazy:
Daniel_Cortez
11.05.2016, 05:11
new i = 100;
to
new i[1 char];
i{0} = 100;
:crazy:
И в чём профит (кроме мазохизма с массивом из 1 элемента)?
Nexius_Tailer
11.05.2016, 12:32
new i = 100;
to
new i[1 char];
i{0} = 100;
:crazy:
Какой толк экономить память (да ещё и такое ничтожное количество), если процессорное время дороже?
TheMallard
11.05.2016, 14:03
Микрооптимизации вообще невыгодны по своей сути.
И в чём профит (кроме мазохизма с массивом из 1 элемента)?
Тем более обращение к ячейке массива всегда медленнее, чем обращение к обычной переменной.
Daniel_Cortez
11.05.2016, 16:54
Какой толк экономить память (да ещё и такое ничтожное количество), если процессорное время дороже?
Тем более обращение к ячейке массива всегда медленнее, чем обращение к обычной переменной.
Дело даже не в этом.
Если честно, я надеялся получить ответ от Geebrox, но раз он решил покинуть сию тему, мне придётся самому расставить точки над "ё".
Никто не заметил самого главного: никакой "экономии памяти" в том подходе с "1 char" нет. Нельзя сделать массив размером в четверть ячейки, полторы ячейки, etc. - в любом случае размер будет округлён до целой ячейки, так работает оператор char (http://pro-pawn.ru/showthread.php?13706).
Nash_Brigers
11.05.2016, 17:29
Дело даже не в этом.
Если честно, я надеялся получить ответ от Geebrox, но раз он решил покинуть сию тему, мне придётся самому расставить точки над "ё".
Никто не заметил самого главного: никакой "экономии памяти" в том подходе с "1 char" нет. Нельзя сделать массив размером в четверть ячейки, полторы ячейки, etc. - в любом случае размер будет округлён до целой ячейки, так работает оператор char (http://pro-pawn.ru/showthread.php?13706).Я хотел об этом написать, но после того как Londlem не обратил на это внимания - решил не вмешиваться))
Nexius_Tailer
11.05.2016, 20:27
Дело даже не в этом.
Если честно, я надеялся получить ответ от Geebrox, но раз он решил покинуть сию тему, мне придётся самому расставить точки над "ё".
Никто не заметил самого главного: никакой "экономии памяти" в том подходе с "1 char" нет. Нельзя сделать массив размером в четверть ячейки, полторы ячейки, etc. - в любом случае размер будет округлён до целой ячейки, так работает оператор char (http://pro-pawn.ru/showthread.php?13706).
А я проверил. Вышло вроде даже больше в итоге, но даже если бы это работало, лично я не вижу смысла от такого экономия памяти вообще, потому что чаще всего ради этого жертвуется скорость, которая важнее.
Разве я писал что так будет быстрее или памяти меньше уйдет?
Я не просто так поставил этот смайл: :crazy:
Мда, критики уровень "Бог"
Если я хотел бы что то доказать, я обязательно об этом написал бы...
Daniel_Cortez
12.05.2016, 06:03
Разве я писал что так будет быстрее или памяти меньше уйдет?
Я не просто так поставил этот смайл: :crazy:
Мда, критики уровень "Бог"
Если я хотел бы что то доказать, я обязательно об этом написал бы...
Всегда удивлялся таким людям: сначала напакостят в теме, а потом пытаются в чём-то обвинить других.
Я не знаю, пытались ли вы намеренно ввести других пользователей в заблуждение, что-то предложить, не зная теории, или это был просто троллинг - в любом случае начали это вы, и теперь ваша попытка выставить себя белым и пушистым выглядит цинично.
Daniel_Cortez
14.08.2016, 13:41
Исправлен краш, возникавший при использовании стандартного компилятора Pawn (до этого я использовал при тестировании только модифицированный компилятор от Zeex). Суть в том, что если использовать #emit сразу же после блока if, то созданные с помощью #emit инструкции почему-то попадают в тот блок.
Иными словами, код
if(i==0)
SendClientMessageToAll(0, str);
#emit push.c str
#emit push.c 0xFFFFFFFF
#emit push.c 8
превращается компилятором в
if(i==0)
{
SendClientMessageToAll(0, str);
#emit push.c str
#emit push.c 0xFFFFFFFF
#emit push.c 8
}
Zeex уже знает об этом баге (https://github.com/Zeex/pawn/wiki/Known-compiler-bugs), но ещё не исправил его в своей версии компилятора.
Проблема проявлялась только при использовании стандартного компилятора, т.к. только при его использовании компилировался блок if. Решена она была следующим образом: после блока if я добавил "i = 100;" - это действие не имеет никакого смысла (т.к. переменная i уже создаётся с изначальным значением 100), но позволяет отделить #emit от if.
if(i==0)
SendClientMessageToAll(0, str);
i = 100;
#emit push.c str
#emit push.c 0xFFFFFFFF
#emit push.c 8
А это не поможет?
if(i==0) {
SendClientMessageToAll(0, str);
}
Daniel_Cortez
14.08.2016, 15:24
А это не поможет?
if(i==0) {
SendClientMessageToAll(0, str);
}
Нет, дело в неправильном адресе в инструкции перехода после проверки условия. Если сразу после тела if использовать #emit, адрес перехода всегда оказывается после #emit.
Нет, дело в неправильном адресе в инструкции перехода после проверки условия. Если сразу после тела if использовать #emit, адрес перехода всегда оказывается после #emit.
Понял, а если так?
do {
SendClientMessageToAll(0, str);
} while (false);
Daniel_Cortez
14.08.2016, 19:30
Понял, а если так?
do {
SendClientMessageToAll(0, str);
} while (false);
Тело ветвления (или цикла в твоём случае) не должно выполняться. Нужно всего лишь зареференсить нативную функцию, прежде чем использовать её в #emit.
В принципе можно вместо if сделать отдельную функцию с атрибутом public и в ней перечислить нужные нативки. Я бы так и сделал с самого начала, но, ИМХО, для такой небольшой работы, как эта, всё будет куда лучше выглядеть в пределах одной функции.
Ещё есть такой вариант: не запихивать вызов SCMA ни в какие ветвления или циклы, а сам цикл do-while ниже сделать на 99 итераций вместо 100. Я подумаю насчёт его применения.
Поставил на сервер месяц назад только сейчас заметил фриз при использование команды, возможно ли как нибудь избежать этого фриза? Или только уменьшением кол. повтора цикла?
Daniel_Cortez
10.10.2016, 07:45
Поставил на сервер месяц назад только сейчас заметил фриз при использование команды, возможно ли как нибудь избежать этого фриза? Или только уменьшением кол. повтора цикла?
Смотря, что вы имеете в виду под "фризом" (разве это так сложно выражаться нормальным языком?)
Если вы про временное зависание игры, то это проблема клиента, а не моего кода. Уменьшение количества итераций может помочь, но тогда игроки всё ещё смогут увидеть часть стёртого чата, прокрутив его вверх.
Автор, будьте добры, почистите немного свой ПМ.
Хотелось бы попросить разрешение на публикацию.
Заранее спасибо.
Nexius_Tailer
02.11.2016, 22:53
Такими темпами скоро и системы приветствия сервера такими же востребованными будут
Daniel_Cortez
03.11.2016, 08:47
Такими темпами скоро и системы приветствия сервера такими же востребованными будут
Добавил пояснение в 1-й пост.
P.S.: Данная команда представляет собой всего лишь пример оптимизации с помощью #emit (в частности, пропуска передачи через стек одних и тех же аргументов функции при её многократном вызове). Данный приём, как и любой другой, связанный с #emit, имеет смысл только для оптимизации самых узких мест, влияющих на производительность сервера.
Но всё же странно. Всегда думал, что это и без пояснений очевидно, но, похоже, что для кого-то нет.
Nexius_Tailer
03.11.2016, 16:06
Кто-то не понял сарказма, это было скорее #enotya адресовано
Исправлен краш, возникавший при использовании стандартного компилятора Pawn (до этого я использовал при тестировании только модифицированный компилятор от Zeex). Суть в том, что если использовать #emit сразу же после блока if, то созданные с помощью #emit инструкции почему-то попадают в тот блок.
Иными словами, код
if(i==0)
SendClientMessageToAll(0, str);
#emit push.c str
#emit push.c 0xFFFFFFFF
#emit push.c 8
превращается компилятором в
if(i==0)
{
SendClientMessageToAll(0, str);
#emit push.c str
#emit push.c 0xFFFFFFFF
#emit push.c 8
}
Zeex уже знает об этом баге (https://github.com/Zeex/pawn/wiki/Known-compiler-bugs), но ещё не исправил его в своей версии компилятора.
Проблема проявлялась только при использовании стандартного компилятора, т.к. только при его использовании компилировался блок if. Решена она была следующим образом: после блока if я добавил "i = 100;" - это действие не имеет никакого смысла (т.к. переменная i уже создаётся с изначальным значением 100), но позволяет отделить #emit от if.
if(i==0)
SendClientMessageToAll(0, str);
i = 100;
#emit push.c str
#emit push.c 0xFFFFFFFF
#emit push.c 8
Это ещё можно исправить таким образом:
if (i == 0)
{
SendClientMessageToAll(0, str);
} {}
Не будет генерироваться лишних инструкций.
Что было:
zero.pri
push.pri
push.c 8
sysreq.c 2 ; SendClientMessageToAll
stack c
l.4
const.pri 64
stor.s.pri fffffffc
push.c 4
push.c ffffffff
push.c 8
Что стало:
zero.pri
push.pri
push.c 8
sysreq.c 2 ; SendClientMessageToAll
stack c
l.4
push.c 4
push.c ffffffff
push.c 8
Daniel_Cortez
26.12.2016, 17:10
Это ещё можно исправить таким образом:
if (i == 0)
{
SendClientMessageToAll(0, str);
} {}
Или так:
{ if(0 == i) SendClientMessageToAll(0, str); }
ИМХО, более эстетичный способ, но да, суть всё та же: нужен пустой локальный блок, чтобы обойти баг с наименьшими потерями.
Обновил 1-й пост.
Пытался реализовать подобное для SendClientMessage, но в итоге так ничего и не вышло, и пару вопросов возникло,
// передать параметры для SendClientMessageToAll
#emit push.c str
#emit push.c 0xFFFFFFFF
#emit push.c 8
Что это за аргумент #emit push.c 8?
static const str[] = "";
new i = 100;
#if __Pawn < 0x030A
{ if(0 == i) SendClientMessage(playerid,0,str); }
#endif
#emit push.c playerid
#emit push.c 0xFFFFFFFF
#emit push.c str
do{
#emit sysreq.c SendClientMessage
}while(--i);
#emit stack 12
Daniel_Cortez
12.07.2017, 15:58
Общий размер аргументов функции в байтах: 2 * (cellbits / charbits).
Окей, но работать всё равно не хочет. Что не так?
static const str[] = "";
new i = 100;
#if __Pawn < 0x030A
{ if(0 == i) SendClientMessage(playerid, 0, str); }
#endif
#emit push.c playerid
#emit push.c 0xFFFFFFFF
#emit push.c str
#emit push.c 8
do{
#emit sysreq.c SendClientMessage
}while(--i);
#emit stack 12
Daniel_Cortez
12.07.2017, 16:18
Вы не знаете самых основ #emit и ждёте, что всё сделают за вас, вот что не так. Изучите теорию, потом уже пытайтесь адаптировать чужой код. На оффе есть несколько хороших уроков.
Powered by vBulletin® Version 4.2.0 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot