[Tutorial] Memуria na Otimizaзгo
#1

Memуria na Otimizaзгo
Aprenda a deixar seus cуdigos mais bonitos e otimizados!
Нndice
  • 1.0 Introduзгo
  • 1.1 Prй-requisitos
  • 1.2 Mйtodo de benchmark
  • 2.0 Criaзгo de variбveis locais
  • 2.1 Entendendo o problema
  • 2.2 Otimizando com variбveis globais
  • 2.3 Resultados
  • 3.0 Consideraзхes finais
1. Introduзгo
  • Primeiro, quero deixar bem claro que este tutorial serб extremamente superficial, e ideolуgico. Й impossнvel eu explicar todos os casos possнveis para utilizar este mйtodo em otimizaзгo de cуdigos, pois sгo infinitas as possibilidades em que este mйtodo й cabнvel. A ideia que serб passada aqui й genйrica e pode ser utilizada para resolver vбrios problemas. Tenha a consciкncia de que normalmente o primeiro bloco de cуdigo que vocк escreve na maioria das vezes nгo й o mais otimizado. Tambйm nгo vou falar de outras tйcnicas como SWITCH, simplificaзгo de condiзгo, etc, pois a ideia aqui й evitar ao mбximo o uso excessivo de variбveis locais.
1.1 Prй-requisitos
  • Й crucial que se pelo menos entenda como funcionam as variбveis, sendo globais, locais, matrizes ou vetores. Caso vocк nгo conheзa ou nгo domine, recomendo que primeiro leia este tutorial do grande rjjj: https://sampforum.blast.hk/showthread.php?tid=235924
1.2 Mйtodo de benchmark
  • Usando o mйtodo do Slice: https://sampforum.blast.hk/showthread.php?tid=218491 Todos os testes de benchmark rodaram por pelo menos 1 minuto em cada teste para evitar picos de processamento, e foram feitos em 3 processadores diferentes: Core i5-4690, Xeon E5450, e Pentium E2200, todos em modo de ALTO DESEMPENHO. Todos os dados serгo apresentados em forma de grбfico de barras, em mйdia de execuзхes por milissegundo. Quanto mais alta a barra, melhor.
2. Criaзгo de variбveis locais
  • Um dos problemas mais comum que me deparo neste fуrum, й a criaзгo e destruiзгo de variбveis locais onde nem sempre se faz necessбrio. Talvez a funзгo mais comum seja a funзгo simplificada de GetPlayerName que ao invйs de passar o nick do jogador por referкncia, passa por retorno:
    PHP код:
    stock GetName(playerid)
    {
        new 
    name[24];
        
    GetPlayerName(playerid,name,24);
        return 
    name;
    }
    // Sendo comumente utilizada em format
    format(string,100,"Seu nome й: %s",GetName(playerid)); 
2.1 Entendendo o problema
  • Mesmo parecendo ser uma funзгo inocente, toda vez que й chamada ela cria um vetor de 24 cйlulas, e logo apуs mandar o resultado para a funзгo format, destrуi essa mesma variбvel.
2.2 Otimizando com variбveis globais
  • A primeira soluзгo, й criar uma variбvel global para evitar criar e destruir um vetor toda vez que precisar-mos desta informaзгo.
    PHP код:
    new pName[24];
    stock GetName(playerid)
    {
        
    GetPlayerName(playerid,pName,24);
        return 
    pName;
    }
    format(string,100,"Seu nome й: %s",GetName(playerid)); 
  • Mesmo que evitamos a criaзгo e destruiзгo desta variбvel, ainda podemos evitar a funзгo GetPlayerName ser chamada sempre. Basta tornar este vetor em uma matriz per-player e entгo obter o nome do jogador quando ele se conecta. Caso vocк use SetPlayerName por qualquer motivo, nгo se esqueзa de setar o valor de pName para o novo nick do jogador, ou o antigo serб usado no lugar.
    PHP код:
    new pName[MAX_PLAYERS][24];
    // Em OnPlayerConnect
    GetPlayerName(playerid,pName[playerid],24);
    // Toda vez que quiser o nick do jogador, vocк nгo precisa mais de funзгo alguma, afinal ja temos o valor na memуria!
    format(string,100,"Seu nome й: %s",pName[playerid]); 
2.3 Resultados
  • A funзхes de format foram incluнdas nos testes de performance, sendo o eixo Y referente а execuзхes por milissegundo.

3. Consideraзхes finais
  • Espero que tenham entendido a ideia deste tutorial. Mesmo sendo curto, creio eu que a ideologia ficou bem explicada. Vocк deve abusar de variбveis globais, mas sempre ficando atento ao consumo de memуria do servidor, mesmo o uso sendo baixнssimo comparado a outras aplicaзхes. Use a memoria do servidor sempre que puder evitar o processador. Nгo deixe de comentar alguma crнtica ou sugestгo.
Reply
#2

Nгo consegui entender esse seu grбfico, o que exatamente vocк estб comparando? o que significa o Y-axis?
Reply
#3

Sem dъvida й um erro que muitos comentem, inclusive eu.
Ainda atingiu o coraзгo do problema que й a funзгo, acredito eu a mais utilizada, GetPlayerName.
Bom tuto! Curto, porйm objetivo!
Reply
#4

Pelo titulo do tуpico confesso que eu esperava algo mais, o certo seria "Manipulando cйlulas" ou "Arrays global" mas creio que nenhum desses tнtulos se encaixaria no tutorial. Eu achei tutorial meio incompleto tambйm pois vocк teria que explicar qual o tamanho da variбvel na memуria, dizer oque й memуria stack e heap qual a diferenзa delas, como conseguir um valor de uma variбvel acessando diretamente na memуria.

Bom trabalho.
Reply
#5

Quote:
Originally Posted by zSuYaNw
Посмотреть сообщение
Pelo titulo do tуpico confesso que eu esperava algo mais, o certo seria "Manipulando cйlulas" ou "Arrays global" mas creio que nenhum desses tнtulos se encaixaria no tutorial. Eu achei tutorial meio incompleto tambйm pois vocк teria que explicar qual o tamanho da variбvel na memуria, dizer oque й memуria stack e heap qual a diferenзa delas, como conseguir um valor de uma variбvel acessando diretamente na memуria.

Bom trabalho.
O objetivo й ser bem superficial mesmo, uma explicaзгo rбpida do assunto para atiзar a busca por informaзгo.
Reply
#6

Pra bom entendedor meia palavra basta, ficou muito bom esse tutorial, com grбfico entгo matou a pau.


Sabem porque Dini foi devassada por outros mйtodos de arquivos .ini? Porque a cada Dini_Get ela precisava ler todo arquivo, entгo vocк acabava perdendo muito tempo com isto

Assim foram saindo novos mйtodos de leitura, que vocк usa File Open para deixar o arquivo na memуria vocк editava ele direto na memуria e depois finalmente dava File Save

Qual desvantagem de usar a memуria assim? Praticamente nenhuma, vocк sу teria reais problemas se o arquivo fosse maior que 1 ou 2 GB, porque dessa forma iria consumir uma RAM do caralho


Resumindo. Usar memуria й sempre mais eficiente, na maioria dos casos, esse exemplo do GetPlayerName й perfeito.


Existem outros mйtodos de usar a memуria. PVAR, GVAR entre outros. No caso de arquivos muito grandes, o melhor mesmo й usar fseek pra pegar apenas uma parte em especifico. Lembra da include do RyDeR chamada mapAndreas?



De modo geral, sempre usem static ao invйs de news. Й sempre, sempre mais otimizado, porque por padrгo as funзхes de SAMP resetam a vбriavel.

Entгo
Quote:

static playername[24];
GetPlayerName(playerid, playername, 24);

terб o mesmo efeito que usar variбveis globais. Por favor, coloque sobre statics no tutorial
Reply
#7

Quote:
Originally Posted by ipsBruno
Посмотреть сообщение
static playername[24];
GetPlayerName(playerid, playername, 24);
Partiu mudar.
Reply
#8

Bruno incluiu algo realmente importante, o uso do static. Devia falar sobre, mas foi um bom tutorial. Bem bбsico mas ъtil.
Reply
#9

Muito bom, mexeu no fundo do problema.
Serve de aviso para muitos, como eu, Tenho essa variavel global, mas geralmente utilizo o GetPlayerName.
Sу que vocк pegar um GM e refazer tudo isso й foda, entгo, vale lembrar, ir fazendo diferente a frente, pois й muito dificil pegar um GM com mais de 70 mil linhas e mudar tudo.

Abraзos.
Reply
#10

Й um tutorial bem simples mas acho que pode ajudar novatos. Bom trabalho.
Reply
#11

Assim й mais bonito:
pawn Код:
static stock GetName(playerid)
{
    static pName[24];
    GetPlayerName(playerid,pName,24);
    return pName;
}
Embora 'static stock GetName' tenha a mesma velocidade aparentemente de 'stock GetName' eu prefiro por ser mais bonito haha, e tmb as duas sгo globais.

A ultima vez que eu fiz teste de velocidade nesse mesmo caso entre
- Static GetName(playerid)
- stock GetName(playerid)
- GetName(playerid)

por incrнvel que pareзa, "stock GetName(playerid)" deu alguns 'ms' mais rбpido, sу que bem pouco. Agora nгo sei lhe falar se й realmente mais rбpido.

pawn Код:
#include <a_samp>

stock Velocidade()
{
    return 10;
}
/*Velocidade()
{
    return 10;
}
static stock Velocidade()
{
    return 10;
}
*/

#define maxloop     (100000)   //loops para teste

public OnGameModeInit()
{
    //==========================================================================

    new
        bCount = GetTickCount();
    for(new i; i < maxloop; ++i)
    {
        printf("Is %d",Velocidade());
    }
    printf("[Velocidade] Functions: %d - Temp: %d",maxloop,(GetTickCount()  - bCount));

//==========================================================================

    return true;
}
=> Cуdigo de velocidade do ipsBruno <=

De qual quer forma, tutorial muito bem organizado, parabйns arakuta.
Reply
#12

Concordo com vocк Xandy, mas tem aquele negуcio, se vocк tornar a variбvel responsбvel por getar o nome, e colocб-la global, vocк nгo terб que criar vбrias e vбrias vezes a mesma variбvel ao chamar a stock.
Reply
#13

Gostei do tutorial, excelente esqueleto e bom conteъdo!

Quote:
Originally Posted by ipsBruno
Посмотреть сообщение
De modo geral, sempre usem static ao invйs de news. Й sempre, sempre mais otimizado, porque por padrгo as funзхes de SAMP resetam a vбriavel.

Entгo


terб o mesmo efeito que usar variбveis globais. Por favor, coloque sobre statics no tutorial
Sу tem um porйm nisso, й saber quando utilizar static. Se vc for levar ao pй da letra e sempre substituir new por static, se encontrarб em um mar de problemas se estiver a declarar static em funзхes per-player, uma vez que enquanto uma funзгo estiver sendo executada, outra execuзгo pode alterar a variбvel estбtica, isso claro dependendo do que aplicar no cуdigo, e no fim irб alterar a variбvel tb para as outras execuзхes, entrando em conflito total.

Considere o seguinte cуdigo:
PHP код:
public OnPlayerConnect(playerid)
{
    
SetTimerEx("Timer"1000true"i"playerid);
}
forward Timer(playerid);
public 
Timer(playerid)
{
    static var;
    var++;
    
printf("player %d: %d"playerid, var);

O cуd acima deveria imprimir no console uma contagem de 1 em 1 seg por player, todavia, quando a mesma estiver em execuзгo para um player e outro concectar-se, o ciclo nгo serб o mesmo, pois a vбriavel estatнstica em questгo estarб sendo utilizada por duas execuзхes em repetiзгo. Isso se deve ao fato de que a variбvel estбtica nгo й resetada no fim do escopo em que й criada.

Concluindo, uma variбvel new seria o mais ideal para situaзхes como tal.
Reply
#14

Quote:
Originally Posted by Bruno13
Посмотреть сообщение
Gostei do tutorial, excelente esqueleto e bom conteъdo!



Sу tem um porйm nisso, й saber quando utilizar static. Se vc for levar ao pй da letra e sempre substituir new por static, se encontrarб em um mar de problemas se estiver a declarar static em funзхes per-player, uma vez que enquanto uma funзгo estiver sendo executada, outra execuзгo pode alterar a variбvel estбtica, isso claro dependendo do que aplicar no cуdigo, e no fim irб alterar a variбvel tb para as outras execuзхes, entrando em conflito total.

Considere o seguinte cуdigo:
PHP код:
public OnPlayerConnect(playerid)
{
    
SetTimerEx("Timer"1000true"i"playerid);
}
forward Timer(playerid);
public 
Timer(playerid)
{
    static var;
    var++;
    
printf("player %d: %d"playerid, var);

O cуd acima deveria imprimir no console uma contagem de 1 em 1 seg por player, todavia, quando a mesma estiver em execuзгo para um player e outro concectar-se, o ciclo nгo serб o mesmo, pois a vбriavel estatнstica em questгo estarб sendo utilizada por duas execuзхes em repetiзгo. Isso se deve ao fato de que a variбvel estбtica nгo й resetada no fim do escopo em que й criada.

Concluindo, uma variбvel new seria o mais ideal para situaзхes como tal.
Deixe-me eu ser mais claro:

Quote:

De modo geral, sempre usem static ao invйs de news. Й sempre, sempre mais otimizado, porque por padrгo as funзхes de SAMP resetam a vбriavel

Ou seja, sу aplique static onde houver funзхes em SA:MP dentro delas, Como GetPlayerName, GetPlayerIp coisas do tipo

Caso contrбrio


PHP код:
static var; var = 0
ou

PHP код:
static var[128]; var[0] = EOS
no caso de strings. Й ainda assim mais rбpido.




Quote:
Originally Posted by XandyMello
Посмотреть сообщение
Assim й mais bonito:
pawn Код:
static stock GetName(playerid)
{
    static pName[24];
    GetPlayerName(playerid,pName,24);
    return pName;
}
Embora 'static stock GetName' tenha a mesma velocidade aparentemente de 'stock GetName' eu prefiro por ser mais bonito haha, e tmb as duas sгo globais.

A ultima vez que eu fiz teste de velocidade nesse mesmo caso entre
- Static GetName(playerid)
- stock GetName(playerid)
- GetName(playerid)

por incrнvel que pareзa, "stock GetName(playerid)" deu alguns 'ms' mais rбpido, sу que bem pouco. Agora nгo sei lhe falar se й realmente mais rбpido.

pawn Код:
#include <a_samp>

stock Velocidade()
{
    return 10;
}
/*Velocidade()
{
    return 10;
}
static stock Velocidade()
{
    return 10;
}
*/

#define maxloop     (100000)   //loops para teste

public OnGameModeInit()
{
    //==========================================================================

    new
        bCount = GetTickCount();
    for(new i; i < maxloop; ++i)
    {
        printf("Is %d",Velocidade());
    }
    printf("[Velocidade] Functions: %d - Temp: %d",maxloop,(GetTickCount()  - bCount));

//==========================================================================

    return true;
}
=> Cуdigo de velocidade do ipsBruno <=

De qual quer forma, tutorial muito bem organizado, parabйns arakuta.

Boa noite Xandy

No caso de static stock й possнvel sim... Stock й para nгo der warnings na hora de compilar de "funзao X nгo foi usada. Te obrigando a usar "#pragma unused FUNCAO". E static nesse caso nгo tem utilidade alguma senгo encher mais o cуdigo NESTE CASO .. Por isto deu alguns segundos mais lentos. E outra coisa. Static nгo se usa fora de escopo, й desnecessбrio. Uma vez que toda variбvel fora de escopo й global por si sу e nгo sгo redeclaradas


Com relaзгo ao uso de stock nгo tem utilidade nenhuma. Sу usam para nгo ficar dando warnings chatos no operador. Й sempre melhor deixar a funзгo limpa por si sу que й mais rбpido. Apesar de feio

pawn Код:
bruno() { return true ; }
Leia: https://sampforum.blast.hk/showthread.php?tid=570635


E outra coisa. Stock й serve pra arrays e variaveis tambйm

PHP код:
stock var ;
var = 
1;
printf("%d', var);
vai imprimir 1 
Sobre otimizaзгo de stocks. Sempre use CONST. Afinal, uma funзгo й imutбvel, ela sempre permanece seu valor constante. Portanto й stock const para uma melhor eficiencia de memуria.

Leia no final deste tutorial: https://sampforum.blast.hk/showthread.php?tid=216730


Abraзo
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)