Memуria na Otimizaзгo -
arakuta - 19.08.2016
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
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.
Re: Memуria na Otimizaзгo -
WLSF - 19.08.2016
Nгo consegui entender esse seu grбfico, o que exatamente vocк estб comparando? o que significa o Y-axis?
Re: Memуria na Otimizaзгo -
F1N4L - 19.08.2016
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!
Re: Memуria na Otimizaзгo -
zSuYaNw - 19.08.2016
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.
Re: Memуria na Otimizaзгo -
arakuta - 20.08.2016
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.
Respuesta: Memуria na Otimizaзгo -
ipsBruno - 20.08.2016
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
Re: Respuesta: Memуria na Otimizaзгo -
Dishz - 20.08.2016
Quote:
Originally Posted by ipsBruno
static playername[24];
GetPlayerName(playerid, playername, 24);
|
Partiu mudar.
Re: Memуria na Otimizaзгo -
RiqueP - 20.08.2016
Bruno incluiu algo realmente importante, o uso do static. Devia falar sobre, mas foi um bom tutorial. Bem bбsico mas ъtil.
Re: Memуria na Otimizaзгo -
matheusspohr - 21.08.2016
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.
Re: Memуria na Otimizaзгo -
YtZ - 22.08.2016
Й um tutorial bem simples mas acho que pode ajudar novatos. Bom trabalho.
Re: Memуria na Otimizaзгo -
XandyMello - 23.08.2016
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.
Re: Memуria na Otimizaзгo -
pWesley - 23.08.2016
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.
Re: Respuesta: Memуria na Otimizaзгo -
Bruno13 - 23.08.2016
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", 1000, true, "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.
Respuesta: Re: Respuesta: Memуria na Otimizaзгo -
ipsBruno - 28.08.2016
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", 1000, true, "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