Timers no Pawn: como usar sem derrubar o desempenho
Timers executam uma função depois de um intervalo, uma vez ou repetidamente. São indispensáveis (salário, fome, relógio, anúncios), mas timers mal usados estão entre as causas mais comuns de lag em servidores open.mp.
SetTimer e SetTimerEx
forward AtualizarRelogio();
public AtualizarRelogio()
{
// roda para o servidor inteiro
return 1;
}
// em OnGameModeInit
SetTimer("AtualizarRelogio", 60000, true); // a cada 60 s, repetindo
Para passar parâmetros, como o playerid, use SetTimerEx:
forward LiberarJogador(playerid);
public LiberarJogador(playerid)
{
TogglePlayerControllable(playerid, true);
return 1;
}
SetTimerEx("LiberarJogador", 3000, false, "i", playerid);
A função chamada precisa ser public e ter forward.
Um timer global em vez de 500 timers por jogador
Um erro clássico é criar um timer repetitivo para cada jogador. Com 300 jogadores online, são 300 timers disparando o tempo todo.
Na maioria dos casos, um timer global que percorre os jogadores resolve com menos custo:
forward TickJogadores();
public TickJogadores()
{
for (new i = 0, j = GetPlayerPoolSize(); i <= j; i++)
{
if (!IsPlayerConnected(i)) continue;
// fome, sede, tempo online...
}
return 1;
}
SetTimer("TickJogadores", 1000, true);
Escolha o intervalo certo
- Salário e pagamentos: minutos;
- Fome e sede: dezenas de segundos;
- Velocímetro e HUD: centenas de milissegundos, só quando necessário;
- Anti-cheat: depende da checagem, mas evite rodar tudo a cada 100 ms.
Quanto menor o intervalo, maior o custo. Pergunte-se se o jogador realmente percebe a diferença.
Mate os timers que não usa mais
Guarde o ID e use KillTimer:
new TimerVelocimetro[MAX_PLAYERS] = {-1, ...};
// ao entrar no veículo
TimerVelocimetro[playerid] = SetTimerEx("AtualizarVelocimetro", 250, true, "i", playerid);
// ao sair do veículo ou desconectar
if (TimerVelocimetro[playerid] != -1)
{
KillTimer(TimerVelocimetro[playerid]);
TimerVelocimetro[playerid] = -1;
}
Timers "órfãos" de jogadores que já saíram continuam rodando e podem agir sobre outro jogador que recebeu o mesmo ID. Esse é um bug difícil de rastrear.
Timers x OnPlayerUpdate
OnPlayerUpdate é chamado muitas vezes por segundo para cada jogador. Mover lógica para lá "porque é mais rápido" costuma piorar o desempenho. Prefira timers com intervalos razoáveis.
Alternativas
Bibliotecas como o YSI oferecem timers declarativos (task e ptask) que deixam o código mais limpo. O princípio é o mesmo: poucos timers e intervalos sensatos.
Hospede seu servidor com a VittHost
Nos planos OPENMP-BR da VittHost, você acompanha o uso de CPU do servidor pelo painel Pterodactyl e percebe rápido quando um timer pesa demais. Servidores no Brasil, proteção DDoS, MySQL incluso, compatibilidade total com scripts SA-MP e teste grátis de 3 dias.