SSGamers - 10 Anos online por você.

Gostaria de reagir a esta mensagem? Crie uma conta em poucos cliques ou inicie sessão para continuar.

Economia de memória para grandes Strings

Weslley_Script
Weslley_Script
SS - Fundador
SS - Fundador


Steam Steam : WeslleySSGames
Zello : WeslleySSGames
Mensagens : 9464
Moedas : 1025828
Data de inscrição : 06/10/2011
Idade : 26
Localização : Brasil

Economia de memória para grandes Strings Empty Economia de memória para grandes Strings

Mensagem por Weslley_Script Qui 26 Ago 2021 - 17:51

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 caractere 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 caractere (inclusive os especiais).
Sendo assim, a maneira mais eficiente de armazenar uma mensagem dentro de uma string não é inserindo um caractere por cell (4B), e sim um caractere por byte, ou seja, 4 caracteres por cell.



Como faremos isso?

Fácil, use ' ! ' antes de declarar uma String.

Ao invés de:
Código PHP:
Código:
new String[16] = "Tutorial Maroto"; 

Use:
Código PHP:
Código:
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.vou mostrar uma alternativa.

Existe um comando que 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:
Código PHP:
Código:
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 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 o tutorial.

 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 função.
Código PHP:
Código:
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):
Código PHP:
Código:
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).


Créditos ao JohnBlack.



Economia de memória para grandes Strings D07Xwqb
Economia de memória para grandes Strings Yjab9HN

    Data/hora atual: Sab 27 Nov 2021 - 5:15