Всем привет
Написал небольшой мод, хотел бы спросить у вас, неплоха ли оптимизация и читабелен ли код?
Pastebin - Клик
P.S. Спасибо DeimoS )
Вид для печати
Всем привет
Написал небольшой мод, хотел бы спросить у вас, неплоха ли оптимизация и читабелен ли код?
Pastebin - Клик
P.S. Спасибо DeimoS )
Не в том месте пытаешься искать, что оптимизировать. Оптимизируй алгоритмы, ищи слабые места в моде с помощью профайлера
Код не соответствует мировым стандартам, читаемость кода оставляет желать лучшего.
1. Имена переменных должны быть записаны в смешанном регистре, начиная с нижнего.
Не правильно:
Правильно:PHP код:
new mysql_id;
2. Имена, представляющие типы, должны быть обязательно написаны в смешанном регистре, начиная с верхнего и значения перечислений должны быть записаны в верхнем регистре с нижним подчёркиванием в качестве разделителя.PHP код:
new mysqlHandle;
Не правильно:
Правильно:PHP код:
enum player_info {
ID,
Name[MAX_PLAYER_NAME],
Pass[24],
Language, // 1 - Russian, 2 - English
Sex,
Skin,
};
new pInfo[MAX_PLAYERS][player_info];
Есть еще и другие пункты, но для начала этого будет достаточно.PHP код:
enum E_PLAYER_INFO
{
E_PLAYER_ID,
E_PLAYER_NAME[MAX_PLAYER_NAME],
E_PLAYER_PASS[24],
E_PLAYER_LANGUAGE,
E_PLAYER_SEX,
E_PLAYER_SKIN,
}
new PlayerInfo[MAX_PLAYERS][E_PLAYER_INFO];
Ну это слишком громко сказано :) Нет одного общего стандарта. Стандарты есть лишь у конкретных языков. И от языка к языку они варьируются, исходя из особенностей языков.
Так же, например, есть такая штука, как "Венгерская нотация". А первый твой пункт описан вот тут и там же есть примеры того, как в разных языках используются разные вариации игр с регистром.
Вот в этой теме отобраны адекватные среди наиболее распространённых вариантов оформления кода. И если уж чего-то придерживаться в SA-MP, то приближенного к той теме.
Касаемо просьбы автора.
Первое, что бросилось в глаза - ошибки с вещественными аргументами (указание целых чисел там, где должно быть вещественное число)
Это создаёт лишние вызовы функции floatЦитата:
PHP код:
SetPlayerPos(playerid, 0, 0, 5);
А вот такие конструкции
можно реализовать такЦитата:
PHP код:
if(!strlen(inputtext) || strlen(inputtext) > 24) return Show_Register(playerid);
strmid(pInfo[playerid][Pass], inputtext, 0, 64, 255);
Или же так:PHP код:
if(!(0 <= strlen(inputtext) <= 24)) return Show_Register(playerid);
strmid(pInfo[playerid][Pass], inputtext, 0, 64, 255);
Тем самым не заставляя сервер обращаться к одной и той же нативке для получения одной и той же информации.PHP код:
new len = strlen(inputtext);
if(!len || len > 24) return Show_Register(playerid);
strmid(pInfo[playerid][Pass], inputtext, 0, 64, 255);
Вот эту конструкцию
Вполне можно заменить на такую строку:Цитата:
PHP код:
switch(listitem) {
case 0: pInfo[playerid][Language] = 1;
case 1: pInfo[playerid][Language] = 2;
}
PHP код:
pInfo[playerid][Language] = listitem+1;
Ну и вот, например, тут
ты объявляешь массив "new query[44+24];" до проверок, которые никак не связаны с этим массивом. То бишь, если игрок, например, не ввёл ничего в диалоговое окно и условие " if(!strlen(inputtext)" сработало, прервав дальнейшую обработку кода, этот массив всё равно будет инициализирован, на что потратится время. Достаточно переместить его за проверку и такого уже не будет (а в твоём случае его вообще стоит перенести в конкретное условие, в котором используется массив)Цитата:
PHP код:
case D_LOGIN: {
if(!response) return Kick(playerid);
new query[44+24];
if(!strlen(inputtext) || strlen(inputtext) > 24) return Show_Login(playerid);
if(!strcmp(pInfo[playerid][Pass], inputtext)) {
mysql_format(mysql_id, query, sizeof(query), "SELECT * FROM `accounts` WHERE `Pass`='%s'", inputtext);
mysql_function_query(mysql_id, query, true, "@_LoadAccount", "i", playerid);
} else {
SetPVarInt(playerid, "WrongPass", GetPVarInt(playerid, "WrongPass")+1);
SCM(playerid, -1, "You have entered the wrong password many times, so they were kicked.");
Show_Login(playerid);
if(GetPVarInt(playerid, "WrongPass") >= 3) return Kick(playerid);
}
return true;
}
PHP код:
case D_LOGIN: {
if(!response) return Kick(playerid);
if(!strlen(inputtext) || strlen(inputtext) > 24) return Show_Login(playerid);
if(!strcmp(pInfo[playerid][Pass], inputtext)) {
new query[44+24];
mysql_format(mysql_id, query, sizeof(query), "SELECT * FROM `accounts` WHERE `Pass`='%s'", inputtext);
mysql_function_query(mysql_id, query, true, "@_LoadAccount", "i", playerid);
} else {
SetPVarInt(playerid, "WrongPass", GetPVarInt(playerid, "WrongPass")+1);
SCM(playerid, -1, "You have entered the wrong password many times, so they were kicked.");
Show_Login(playerid);
if(GetPVarInt(playerid, "WrongPass") >= 3) return Kick(playerid);
}
return true;
}
Пока всё
Вызывать регистрацию в OnPlayerConnect, не самый лучший вариант, версия 0.3DL даст о себе знать
- - - Добавлено - - -
Это
НаPHP код:
case D_REG_SEX: {
if(!response) return Kick(playerid);
new rand;
switch(listitem) {
case 0: {
pInfo[playerid][Sex] = 1;
rand = random(sizeof(Random_Skin_Male));
pInfo[playerid][Skin] = Random_Skin_Male[rand];
}
case 1: {
pInfo[playerid][Sex] = 2;
rand = random(sizeof(Random_Skin_Female));
pInfo[playerid][Skin] = Random_Skin_Female[rand];
}
}
CreateNewAccount(playerid);
return true;
}
PHP код:
case D_REG_SEX: {
if(!response) return Kick(playerid);
pInfo[playerid][Sex] = listitem + 1;
pInfo[playerid][Skin] = (listitem == 0)?
(Random_Skin_Male[random(sizeof(Random_Skin_Male))]):(Random_Skin_Female[random(sizeof(Random_Skin_Female))]);
CreateNewAccount(playerid);
return true;
}
Вызывай регистрацию в OnPlayerRequestClass, иначе будет в 0.3DL так
https://image.prntscr.com/image/X37e...2jwSA0MRVA.png
Я бы сделал так:
PHP код:
case D_REG_SEX:
{
if(!response)
return Kick(playerid);
pInfo[playerid][Sex] = listitem + 1;
if(pInfo[playerid][Sex] == 1)
pInfo[playerid][Skin] = Random_Skin_Male[random(sizeof(Random_Skin_Male))];
else
pInfo[playerid][Skin] = Random_Skin_Female[random(sizeof(Random_Skin_Female))];
CreateNewAccount(playerid);
return true;
}
Тоже стоит понимать, что ради компактности ты жертвуешь процессорным временем :)
Тут действует принцип "китайского кода": да, код более объёмный, но все вариации прописаны сразу, за счёт чего не происходит лишних обращений к переменным и прочих действий.
По-хорошему, здесь стоит только от лишней переменной избавится, как это сделал ты
В остальном код оптимален (нет повторных вызовов ни для listitem, ни для pInfo)PHP код:
case D_REG_SEX: {
if(!response) return Kick(playerid);
switch(listitem) {
case 0: {
pInfo[playerid][Sex] = 1;
pInfo[playerid][Skin] = Random_Skin_Male[random(sizeof(Random_Skin_Male)];
}
case 1: {
pInfo[playerid][Sex] = 2;
pInfo[playerid][Skin] = Random_Skin_Female[random(sizeof(Random_Skin_Female)];
}
}
CreateNewAccount(playerid);
return true;
}
Я это вижу как-то так:
Не знаю, быстрее это или нет, но для меня в первую очередь важна читаемость кода, что влечёт за собой уменьшение дублирования кода.PHP код:
case D_REG_SEX: {
if(!response) return Kick(playerid);
pInfo[playerid][Sex] = listitem + 1;
pInfo[playerid][Skin] = Random_Skin[listitem][random(strlen(Random_Skin[listitem])];
CreateNewAccount(playerid);
return true;
}
Ну и такой код более гибок, легче будет добавить новый пол (мало-ли).
Ну значит я правильно понял. Если я правильно представляю принципы, по которым будет обрабатываться сей код, то увы, тут будет больше действий.
И да, надо было сразу уточнить, что про быстродействие я начал говорить не с той целью, что нужно использовать мой вариант, ибо он быстрее, а пытался объяснить (только забыл предупредить об этом :D) на наглядном примере то, что часто оптимизация одного параметра (в данном случае читаемости) наносит "вред" другому параметру (в данном случае быстродействию). И всегда следует выбирать меньшее зло среди всех.
В данном случае, например, оптимизация читаемости (вариант Ziggi и Long-) будут вполне приемлемыми, ибо код вызывается не так часто + сама по себе разница по времени между двумя вариантами минимальна.
Вооот. Ваш кэп :pardon:
Не только читаемости, но и масштабируемости)
// DeimoSPHP код:
for(new i = 0; i < 10000; i++)
// Snegovik1337Цитата:
1) 6 + 6 + 7 + 7 + 6 / 5 = 6.4 //Snegovik1337
2) 7 + 6 + 6 + 6 + 5 / 5 = 6 //DeimoS
3) 8 + 7 + 8 + 7 + 8 / 5 = 7.6 //Long-
PHP код:
for(new i = 0; i < 100000; i++)
// Snegovik1337Цитата:
1) 59 + 63 + 59 + 61 + 61 / 5 = 60.6 //Snegovik1337
2) 60 + 61 + 63 + 68 + 59 / 5 = 62.2 //DeimoS
3) 71 + 69 + 74 + 71 + 71 / 5 = 71.2 //Long-
PHP код:
for(new i = 0; i < 1000000; i++)
Цитата:
1) 545 + 549 + 548 + 555 + 556 / 5 = 550.6 //Snegovik1337
2) 598 + 576 + 604 + 555 + 577 / 5 = 582 //DeimoS
3) 638 + 627 + 626 + 635 + 659 / 5 = 637 //Long-
Написано же, тест на скорость чей вариант быстрее
А исходный код теста увидеть можно?
https://pastebin.com/0ups9v9d
Один из вариантов открываешь, компилируешь и проверяешь результат, потом скрываешь, открываешь другой и так т.д.
Все сразу не стал сделать, ибо не корректно показывает
https://pastebin.com/Xf3hSGL7
С Jit все участки кода будут, примерно, одинаково обрабатываться
Код, кстати, не компилится на компиляторе 3.10.6
https://pastebin.com/h1tmkZpi
Заменил strlen на sizeof, вариант со strlen медленнее на 30-40%. В данном случае скинов у каждого пола по 2, поэтому всё норм.
Забавно, что без каких-либо изменений в коде результаты у меня прямо противоположные
Видимо, особенности процессора или ещё что
- - - Добавлено - - -
Нашел причину. Препроцессор криво обрабатывает перенос строки в макросах. А именно, не ставит пробел на месте переноса, из-за чего вот такой код
Для него становится таким макросомPHP код:
#define test(%0)\
print(%0)
Если поставить пробел между ")" и "\" - всё станет работать нормально.PHP код:
test(%0)print(%0)
Отпишите на github, кому не трудно и кто в ладах с английским