Economia de memуria para grandes Strings -
JohnBlack - 10.04.2018
Este й um tutorial simples e rбpido para vocк compreender algumas coisas bбsicas sobre declaraзгo de vars/arrays em Pawn (1) e como economizar memуria com isso (2).
Vou passar rбpido no tуpico 1 (declaraзгo de vars/arrays em Pawn) e me estender no tуpico 2.
Coisas que vocк precisa saber para entender este tуpico:
- Basicamente, todas as variбveis declaradas em Pawn (seja new, seja static) alocarгo 32 bits (4 bytes ou 4B) p/cell.
- Cells sгo representadas por colchetes var[0] e bytes por chaves var{0}.
- Todo caracter da table ASCII (inclusive os especiais) compreendem nos decimais que vгo de 0 a 255
- 8 bits podem armazenar um nъmero de 0 a 255.
Logo podemos concluir que: 8 bits (1B) sгo suficientes para armazenar qualquer caracter (inclusive os especiais).
Sendo assim, a maneira mais eficiente de armazenar uma mensagem dentro de uma string nгo й inserindo um caracter por cell (4B), e sim um caracter por byte, ou seja, 4 caracteres por cell.
"LOL e como faz isso?"
Fбcil, use ' ! ' antes de declarar uma String. Exemplo:
Ao invйs de
Code:
new String[16] = "Tutorial Maroto";
Use
Code:
new String[4] = !"Tutorial Maroto";
Isso faz com que vocк economize 12 Bytes de um total de 16 (75%).
Imagine fazer isso para um servidor inteiro, a memуria cai muito.
Enfim, tudo tem seus prуs e contras. O nome desse tipo de string, de acordo com Pawn, й packed strings (mensagens compactadas), em que, realmente, alocam uma quantia menor de memуria, mas nгo й possнvel que vocк use a funзгo 'format' com elas, o que ferra tudo, porque sгo muito poucas as strings em um servidor que nгo passem por um format.
Ou seja, esse tutorial й inъtil pode parar de ler por aqui.
Brincadeira, vou mostrar um truque que faзo.
Existe um comando que rola por aн em GameModes chamado /Cores, que basicamente faz com que uma dialog MSGBOX apareзa na tela do player com as 256 cores de veнculos, cada cor com seu respectivo nъmero, tipo isso:
Mas pensa bem, se vocк for armazenar as 3072 caracteres que tem aн dentro (nгo й um palpite, tкm exatos 3072 caracteres), vocк teria que fazer algo mais ou menos assim:
Code:
if(!strcmp(cmd, "/cores", true))
{
new color_list[3072];
for (new colorid; colorid != sizeof gVehicleColors; colorid++)
{
format(color_list, sizeof color_list, "%s{%06x}%03d%s", color_list, gVehicleColors[colorid] >>> 8, colorid, !((colorid + 1) % 16) ? ("\n") : (" "));
}
ShowPlayerDialog(playerid, 1, DIALOG_STYLE_MSGBOX, "Color List", color_list, "Close", "");
return 1;
}
Sim, declarar uma string de fucking 3072 cells, quero dizer 12.288bytes, exatos 12 KILOBYTES.
Serб se conseguimos diminuir para 3 KB? diminuir em 75%? Nгo exatamente, mas conseguimos diminuir muito a memуria alocada, e й agora que comeзa meu tutorial, rs.
Bom, jб que sгo 3072 caracteres, precisamos de apenas 768 cells (3072/4). Comeзamos por aн.
Alйm disso, vamos ter que criar outra array para armazenar a string que serб formatada (usaremos 14 cells).
Por ъltimo, usaremos uma function feita por mim (nгo sei se mais alguйm jб fez antes, mas foi bem facinho entгo nгo me importo de pegarem meus possнveis crйditos, it is not a big deal).
Code:
if(!strcmp(cmd, "/Cores", true)) {
new Result[768]; // Os 3072 caracteres do resultado final
new String[14]; // Os 14 caracteres que serгo formatados a cada looping
for(new i; i != 256; ++i) { // 256 cores
format(String, 14, "{%06x}%03i%s", (VehicleColors[i] >>> 8), i, (((i+1) % 16) ? (" ") : ("\n"))); // Nгo precisa entender isso, apenas que fique claro que estamos usando format
strpack(String, String); // compactando as 14 cells em 14 bytes (que fique claro que a array String NГO diminuiu de tamanho, apenas a informaзгo foi compactada)
strpackcat(Result, String); // juntando a array Result com a array String (formatada e depois compactada)
} // Depois do processo ter terminado, a array Result estarб prontinha para uso
ShowPlayerDialog(playerid, DIALOG_NOANS, DIALOG_STYLE_MSGBOX, "Cores", Result, "Ok", "");
return 1;
}
a stock strpackcat (que basicamente concatena 2 packed strings, como se fosse strcat sу que de packed strings):
Code:
stock strpackcat(dest[], const source[], maxlength=sizeof(dest)) {
if(dest{3}) { if(!dest{0}) { print("JBScript [strpackcat] ERROR: The destiny string must be already packed before using this function."); return 0; } }
if(source{3}) { if(!source{0}) { print("JBScript [strpackcat] ERROR: The source string must be already packed before using this function."); return 0; } }
new dl = strlen(dest), sl = strlen(source);
maxlength *= 4;
if(maxlength < dl) { print("JBScript [strpackcat] ERROR: The maxlength is lesser then destiny string length."); return 0; }
if(maxlength < sl+dl) { sl = maxlength-dl; }
for(new i; i != sl; ++i) { dest{dl+i} = source{i}; }
return 1;
}
Bom, o tutorial й basicamente isso, nгo tгo ъtil atй porque nem sempre criamos uma array assim tгo grande. Й mais usado nesses casos (raros) mesmo.
Algumas coisas eu nгo falei durante o tutorial pois nгo й o foco (jб que devem existir outros tutoriais sobre os detalhes que eu deixei de falar, como o uso de 'char', que basicamente retorna o nъmero de cells que sгo necessбrias para armazenar x caracteres, etc).
Estou trabalhando num projeto (all alone, aceito helps) de aperfeiзoar a funзгo 'format' para que esta possa ser usada em packed strings inclusive. Desta forma tenho a mais clara certeza que esse tutorial serб completamente dispensбvel (no futuro) se eu conseguir chegar a esse resultado um dia. Economizarб mais memуria que Alzheimer.
Fora isso, foi um prazer ajudar vocк (se й que isso ajudou, se й que vocк leu atй aqui) e desculpem pela estйtica (que na realidade nгo dou a mнnima pra isso)
Re: Economia de memуria -
arakuta - 10.04.2018
Й importante conhecer todas as ferramentas disponнvel para otimizar seu servidor. Se falta memуria (o que й raro, se isso estб acontecendo revise seus conceitos) vocк pode compactar e ajustar tamanho das strings. Se falta processador, vocк pode usar mais memуria.
Seu tutorial me chamou a atenзгo para um negуcio: Problema de banda. Aquela tal string de 12MB que vocк citou, na verdade sгo sу 12KB e se o servidor tiver lento, mas com processador sobrando, й possнvel atй fazer packet strings apуs o format antes de enviar para o jogador? Ele envia menos dados para o player, ou nгo?
Ex:
PHP Code:
format(string,200,"Alguma coisa muito longa vai ocupar aqui cerca de 200 caracteres. Depois da formataзгo, %s","serб que fazer repack ajuda no consumo de banda? Quanto a mais de processador consome?");
strpack(stringGlobal,string);
Й algo vбlido em algumas situaзхes
Bom tutorial
cade os crйditos do meu comando? -
RazorGuigo - 10.04.2018
Quote:
Originally Posted by JohnBlack
Sim, declarar uma string de fucking 3072 cells, quero dizer 12.288bytes, exatos 12 MEGABYTES.
|
Sгo 12KB nгo MB
mas o tutorial estб legal, embora eu acho um pouco superfula esta economia nгo vejo uma real melhora para o usuбrio final
Quote:
Originally Posted by arakuta
mas com processador sobrando, й possнvel atй fazer packet strings apуs o format antes de enviar para o jogador? Ele envia menos dados para o player, ou nгo?
|
Essas perguntas sгo importantes explicar no tutorial
Re: cade os crйditos do meu comando? -
JohnBlack - 10.04.2018
Quote:
Originally Posted by RazorGuigo
Sгo 12KB nгo MB mas o tutorial estб legal, embora eu acho um pouco superfula esta economia nгo vejo uma real melhora para o usuбrio final
Essas perguntas sгo importantes explicar no tutorial
|
Meu Deus, devia estar com Parkinson na hora que escrevi. Com certeza sгo 12KB, obrigado por me notificar!
Ps.: O maior motivo desse tutorial ter sido postado й para evitar aquela mensagem que fica no compilador quando vocк excede o limite de memуria (sem usar #pragma kk, isso й algo sem sentido).
Re: Economia de memуria -
XandyMello - 10.04.2018
PHP Code:
new String[] = "Tutorial Maroto";
sizeof String; //Tamanho
Re: Economia de memуria -
arakuta - 10.04.2018
Fiz os testes, e o uso de banda й o mesmo, independente se a string estб empacotada ou nгo
A rede do SA-MP jб faz o envio da string empacotada, sendo assim, aquela string de 12KB na memуria, vai apenas 4KB para o cliente.
Abraзos!