PDA

Просмотр полной версии : [Вопрос] Пару вопросов (опытные сюда пожалуйста :3)



StevenH
14.11.2015, 00:04
Всем привет. Я новичок в павн..

Мне интересно, как лучше использовать стринг? Вот 3 варианта которые я слышал/видел. И что же лучше.

За любой АДЕКВАТНЫЙ ответ жму - спасибо!

1 Вопрос:
1.1. Сейчас я использую так:


new mysqlstr [512];
new string [255];

Везде где есть mysql, я юзаю mysqlstr (сохранение и прочее).
Везде где диалоги/форматы/команды я юзаю string.

1.2. В каждом паблике, например будет OnDialogResponse. Вначале паблика создать стринг например: new dialog_string[255]; и юзать это только в паблике OnDialogResponse.
Так же и с мускулом.

1.3. Возьмём например OnDialogReponse. Вначале нечего не создаём, но создаём например в 1-ом диалоге new (dialog_)string[55]; с подсчётом символов и юзать (Как РакНет например).


// На данный вопрос мне ответил BossArturKA
Cледующий вопрос читайте под его постом!!!

BossArturKA
14.11.2015, 12:25
(если я правильно понял суть вопросов)

В каждом "кусочке" мода лучше создавать уникальное количество ячеек, а не использовать глобальное.

На пример команда:
CMD:myname(playerid, params[]){
new uni_str[22],
GetPlayerName(playerid, uni_str, sizeof(uni_str));
format(uni_str, sizeof(uni_str), "%s.", uni_str), SendClientMessageToAll(-1, uni_str);
return true;
}
на примере диалог:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]){
switch(dialogid){
case 0:{
new uni_str[28];
format(uni_str,sizeof(uni_str),"Вы использовали диалог № %d.", dialogid), SendClientMessage(playerid, -1, uni_str);
}
case 1:{
new uni_str[22];
format(uni_str,sizeof(uni_str),"Ты заюзал диалог № %d.", dialogid), SendClientMessage(playerid, -1, uni_str);
}
}
return false;
}
Ну и запросы MySQL...
Допустим, у нас происходит обновление стоимости дома...
Представим, что у нас на сервере максимальный ID дома 111 а цена 55555.
Возможный запрос: UPDATE house SET price = 55555 WHERE id = 111 LIMIT 1
Соответственно тут использовать глобальные 512 ячеек тоже не разумно.
Имеем:
new uni_str[54];
format(uni_str, sizeof(uni_str), "UPDATE house SET price = %i WHERE id = %i LIMIT 1", hInfo[id][price], id), mysql_function_query(db, uni_str, false, "", "");

StevenH
14.11.2015, 13:00
Цитата BossArturKA

В этом и заключался мой вопрос :). А теперь у меня возникло 3 вопроса.

1. А сильно ли это влияет на мод/оптимизацию и прочее?

И да, как правильно посчитать кол-во ячеек. Где то читал, например что в слове: Привет
не 6 ячеек а 7 (типа в конце пробела нету, но он даёт +1 ячейку).
И есть ли быстрый способ как то посчитать кол-во ячеек?

2. Что обозначает вот это в pawn.cfg:
-d0
-O1 или -O2

Влияет ли это как-то на оптимизацию или ещё что?

3. С помощью ключа -v2 я провёл тест:


Header size: 3624 bytes
Code size: 77688 bytes
Data size: 793096 bytes
Stack/heap size: 16384 bytes; estimated max. usage=324 cells (1296 bytes)
Total requirements: 890792 bytes


Это хорошо или как? Мод пишу с нуля на MySQL R39-3, в моде ~1100 строк. Есть система авторизации/регистрации, домов и прочего.
P.S. сейчас когда делал этот тест у меня стринги глобальные!!! Сейчас буду переводить на уникальные стринги.

Провёл тест с помощью ключа: -v2 и -d0


Header size: 3624 bytes
Code size: 70608 bytes
Data size: 793096 bytes
Stack/heap size: 16384 bytes; estimated max. usage=324 cells (1296 bytes)
Total requirements: 883712 bytes


Цифры другие стали. Если не сложно, объясните что к чему относится.
P.S. сейчас когда делал этот тест у меня стринги глобальные!!! Сейчас буду переводить на уникальные стринги.

BossArturKA
14.11.2015, 14:23
1. Конечно лучше использовать локальные ячейки а не глобальные (память не будешь терять).
1.1 Считается по принципу:
Имеется текст "StevenH", который состоит из семи символов.
Значит нужно создать число ячеек: 7+1 = 8.

1 ячейка: "S".
2 ячейка: "t".
3 ячейка: "e".
4 ячейка: "v".
5 ячейка: "e".
6 ячейка: "n".
7 ячейка: "H".
8 ячейка: "NULL".

NULL в качестве "конца строки".

При формировании текста, %s/%d/%f... не учитываются (Подразумевают дальнейшую прибавку нужного тебе числа от вывода).

Допустим, нужно вывести Привет Nick_Name.
Максимальная длина ника в клиенте SA:MP, 20 символов.
В таком случаи код будет таков:

new uni_str[29];
GetPlayerName(playerid, uni_str, sizeof(uni_str));
format(uni_str, sizeof(uni_str), "Привет %s.", uni_str), SendClientMessageToAll(-1, uni_str);
Почему-же 29 ячеек?
8 ячеек на "Привет ." (Слово, пробел и точка). 20 ячеек на ник игрока. И + 1 на NULL.

Переносы и "визуальная табуляция текста" в диалогах, считается как 1 символ.
Пример:
Привет\nВасяили
Привет\tВася
То есть на это нам нужно 12 ячеек (Текст: ПриветВася + 1 перенос строки/табулирование и + 1 NULL)/

Для подсчета длинных строк, можно воспользоваться онлайном сервисом по запросу "Online strlen" (Хотя способов много).
Есть даже определенный софт,специально для PAWN, который автоматически приравнивает %s,%d,... к нулю а \n, \t... к единицы.

2. Это различного рода "Ключи" для компилирования мода.
Почитать можно тут: КЛИК (http://pro-pawn.ru/showthread.php?7967-Pawncc%28-pawno-pawn-cfg%29) Хотя информация не самая полная. Лучше на официальном портале прочесть об этом.

3. Ключ "-v2" выводит "максимальную детализацию" по компилированию. Сложно что либо сказать от сюда...
Удали данный ключ (Или, поставь на 1, как по умолчанию).
Тогда будешь получать предупреждения, на которые стоит реагировать (Типа переполнения стока).

А по твоим результатм, можно сказать только вот что:
Размер стека 12208 байт - у тебя используется 1296. Это хорошо.

StevenH
14.11.2015, 14:38
Ответ от BossArturKA

Спасибо за все разъяснения а так же хороший ответ! Теперь я всё понял. Нажал спасибку полюбому).

UPD: Разве максимальное имя игрока 20 символов? Я читал где-то что 24.
-------------------------------------

1. Как стоит сохранять данные игрока. Только при дисконнекте или например сделал действие - сохранил.
2. Цвет тоже учитывается как ячейки? Например {FF00FF} - прибавлять 8 ячеек?

StevenH
14.11.2015, 15:14
Спасибо.

StevenH
14.11.2015, 16:53
Я перевёл глобальные стринги на уникальные, однако стек повысился. Это нормально?

Stack/heap size: 16384 bytes; estimated max. usage=537 cells (2148 bytes)
А был: 1296..

Что делать?

Daniel_Cortez
14.11.2015, 20:00
Я перевёл глобальные стринги на уникальные, однако стек повысился. Это нормально?

Stack/heap size: 16384 bytes; estimated max. usage=537 cells (2148 bytes)
А был: 1296..

Что делать?
Было 1296, а стало 537? Так это ж наоборот хорошо.

StevenH
14.11.2015, 20:10
Было 1296, а стало 537? Так это ж наоборот хорошо.

Короче, было:

Stack/heap size: 16384 bytes; estimated max. usage=324 cells (1296 bytes)

Стало:

Stack/heap size: 16384 bytes; estimated max. usage=537 cells (2148 bytes)

Получается глобальные стринги лучше, которые создаются вначале или что?

Daniel_Cortez
14.11.2015, 20:44
Короче, было:

Stack/heap size: 16384 bytes; estimated max. usage=324 cells (1296 bytes)

Стало:

Stack/heap size: 16384 bytes; estimated max. usage=537 cells (2148 bytes)

Если вы думаете, что это плохо, то посмотрите на строку "Data size" до и после. Если убрать те глобальные массивы, размер секции данных уменьшится - этим и должно окупиться повысившееся потребление места в стеке.

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

Profyan
14.11.2015, 21:10
Если вы думаете, что это плохо, то посмотрите на строку "Data size" до и после. Если убрать те глобальные массивы, размер секции данных уменьшится - этим и должно окупиться повысившееся потребление места в стеке.

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

Если , например мне нужен массив с 2500 ячейками. Логично его будет сделать глобальным, ведь сразу тогда стек заполнится.Но тогда придется мучатся с очисткой массива каждый раз. Или как вариант сделать этот массив локальным и #pragma dynamic выставить значение, ведь ничего плохого она не делает, лишь увеличивает место. И для инициализации, как вы и сказали, требуется мало времени. Чем не вариант?

Daniel_Cortez
14.11.2015, 21:43
Если , например мне нужен массив с 2500 ячейками.
Интересно, для чего может понадобиться такой огромный массив. В голову приходит только составление списка онлайна игроков, но тут можно немного схитрить, упаковавая строки перед конкатенацией, благодаря чему лимит кол-ва символов в массиве с результатом увеличится в 4 раза.
Ну либо такой массив объявлять при помощи static вместо new - он останется видимым только внутри функции, но находиться будет не в стеке, а в секции данных.
Но это всё только в самом крайнем случае. Как говорится, исключение только подтверждает правило.

Profyan
14.11.2015, 22:12
Интересно, для чего может понадобиться такой огромный массив. В голову приходит только составление списка онлайна игроков, но тут можно немного схитрить, упаковавая строки перед конкатенацией, благодаря чему лимит кол-ва символов в массиве с результатом увеличится в 4 раза.
Ну либо такой массив объявлять при помощи static вместо new - он останется видимым только внутри функции, но находиться будет не в стеке, а в секции данных.
Но это всё только в самом крайнем случае. Как говорится, исключение только подтверждает правило.

Спасибо за 2 примера реализации.