One "global" timer or "Per-player" timer?
#1

I've been thinking stuff about my speedometer timers, and realized that I could just make a 1 global timer, instead of doing it "Per-Player", but.. What's better?
Global Timer: VehicleTimer = SetTimer("VehicleT", 1000, true);
Per-Player Timer: VehicleTimer[ playerid ] = SetTimerEx("VehicleT", 1000, true);

The current good side i see for the Global timer is: Less overall timers
But the bad side is, possible lag?

Here's my speedometer timer callback;
pawn Код:
PUB:VehicleT(playerid)
{
    if(IsPlayerInAnyVehicle(playerid))
    {
        new vID = GetPlayerVehicleID(playerid), string[142], string2[3], Float:rotation, Float:vhealth;
        GetVehicleZAngle(vID, rotation), GetVehicleHealth(vID, vhealth);
        new direction = floatround(rotation,floatround_round);
        while(direction > 360) direction -= 360;
        while(direction < 0) direction += 360;
        switch(direction)
        {
            case 0..22: string2 = "N";
            case 23..67: string2 = "NW";
            case 68..112: string2 = "W";
            case 113..157: string2 = "SW";
            case 158..202: string2 = "S";
            case 203..247: string2 = "SE";
            case 248..292: string2 = "E";
            case 293..337: string2 = "NE";
            case 338..360: string2 = "N";
        }
        format(string, sizeof(string), "~w~VEHICLE: ~y~%s~n~~w~SPEED: ~y~%d KM/H~n~~w~LOCATION: ~y~%s~n~~w~DIRECTION: ~y~%s~n~~w~HEALTH: ~y~%0.0f%%",VehicleNames[GetVehicleModel(vID)-400], GetPlayerSpeed(playerid), GetPlayerArea(playerid), string2, vhealth);
        TextDrawSetString(VehicleInfo[playerid], string);
        TextDrawShowForPlayer(playerid, VehicleInfo[playerid]);
        string = "\0";
    }
    else KillTimer(VehicleTimer[playerid]), TextDrawHideForPlayer(playerid, VehicleInfo[playerid]), TextDrawHideForPlayer(playerid, VehicleBox[playerid]);
    return 1;
}
Should I change something If i want to make it a global timer? (Except the obvious(The playerid, add loop ..))
Reply
#2

Use a single global timer. You'll be calling the same amount of code whether or not it's in a single timer or per-player timers (except for a loop (use foreach)).
Reply
#3

I suggest making a global timer for the one reason you mentioned - less total of timers. Server doesn't have to struggle to keep 100+ (assuming 100 players connected) timers in a queue and you have shorter function(s) execution time, leaving you with enough "processing power" to make some heavy calculations, if you must.
As for the "conversion" I think you're covered here, just make sure not to define variables in a loop.
Reply
#4

If I may add something to ******'s post, because I'd use the per player timers personally, I use the y_timers for basically all of my timers, and I find very interesting the balancing algorithm. If you're worried about memory, I strongly suggest you to use them too.
Reply
#5

https://sampforum.blast.hk/showthread.php?tid=61322

Missed this thread somehow.
Reply
#6

Quote:
Originally Posted by S4t3K
Посмотреть сообщение
If I may add something to ******'s post, because I'd use the per player timers personally, I use the y_timers for basically all of my timers, and I find very interesting the balancing algorithm. If you're worried about memory, I strongly suggest you to use them too.
y_timers look confusing for me :l

Quote:
Originally Posted by Bakr
Посмотреть сообщение
Uh.. Not sure what the "secret message" of that was, but I only have a 1 second main-timer(Others are 5+ seconds(even minutes)), so they shouldn't conflict/do stuff at the same time.

And uh, i'm still confused.
Some of you say to use the 1 timer, but ****** says no :l

@******:
What did you exactly mean with "Either way, the server will have to trigger and run some code for each player, only by not using multiple timers you are basically recreating the timer plumbing in PAWN from scratch (and probably badly). "
I mean, VehicleT is a global var, and it does do "VehicleT[ ... ] = SetTimerEx" each time a player enters a vehicle, but it does get killed when the player exits the vehicle xd
Reply
#7

If you have only one timer (execution time is obviously exaggerated):
Код:
Player sync
Timer called (exec time = 5 seconds)
Timer ends > players go without sync for 5 seconds
Player sync
If you have a single big timer you may experience lag because while it is executing the players cannot sync. However, if you have multiple smaller ones, it chops it up to where players can sync between calls.
Код:
Player sync
Small Timer called (exec time = 1 sec)
Small Timer ends > players go without sync for 1 second
Player sync
Small Timer2 called (exec time = 1 sec)
Small Timer2 ends > players go without sync for 1 second
Player sync
...
This is because we only have a single thread to work with (which I use to look at as a disadvantage).
Reply
#8

I don't see what's so difficult. Start the timer when they enter a vehicle, kill the timer when they leave it.

Per player timers with this logic will make the most efficient option.

pawn Код:
forward SpeedometerUpdate(playerid);
public SpeedometerUpdate(playerid)
{
    if(IsPlayerInAnyVehicle(playerid) && IsPlayerConnected(playerid))
    {
        new vID = GetPlayerVehicleID(playerid), string[142], string2[3], Float:rotation, Float:vhealth;
        GetVehicleZAngle(vID, rotation);
        GetVehicleHealth(vID, vhealth);
        new direction = floatround(rotation, floatround_round);
        while(direction > 360) direction -= 360;
        while(direction < 0) direction += 360;
        switch(direction)
        {
            case 0 .. 22, 338 .. 360: string2 = "N";
            case 23 .. 67: string2 = "NW";
            case 68 .. 112: string2 = "W";
            case 113 .. 157: string2 = "SW";
            case 158 .. 202: string2 = "S";
            case 203 .. 247: string2 = "SE";
            case 248 .. 292: string2 = "E";
            case 293 .. 337: string2 = "NE";
        }
        format(string, sizeof(string), "~w~VEHICLE: ~y~%s~n~~w~SPEED: ~y~%d KM/H~n~~w~LOCATION: ~y~%s~n~~w~DIRECTION: ~y~%s~n~~w~HEALTH: ~y~%0.0f%s", VehicleNames[GetVehicleModel(vID) - 400], GetPlayerSpeed(playerid), GetPlayerArea(playerid), string2, vhealth, "%%");
        TextDrawSetString(VehicleInfo[playerid], string);
        TextDrawShowForPlayer(playerid, VehicleInfo[playerid]);
        string = "\0";
    }
    else
    {
        KillTimer(VehicleTimer[playerid]);
        TextDrawHideForPlayer(playerid, VehicleInfo[playerid]);
        TextDrawHideForPlayer(playerid, VehicleBox[playerid]);
    }
    return 1;
}

public OnPlayerStateChange(playerid, newstate, oldstate)
{
    if(newstate == PLAYER_STATE_DRIVER || newstate == PLAYER_STATE_PASSENGER)
        VehicleTimer[playerid] = SetTimerEx("SpeedometerUpdate", 1000, true, "i", playerid);
    if(newstate == PLAYER_STATE_ONFOOT && (oldstate == PLAYER_STATE_PASSENGER || oldstate == PLAYER_STATE_DRIVER))
        KillTimer(VehicleTimer[playerid]);
    return 1;
}
Reply
#9

Quote:
Originally Posted by Threshold
Посмотреть сообщение
I don't see what's so difficult. Start the timer when they enter a vehicle, kill the timer when they leave it.

Per player timers with this logic will make the most efficient option.

pawn Код:
forward SpeedometerUpdate(playerid);
public SpeedometerUpdate(playerid)
{
    if(IsPlayerInAnyVehicle(playerid) && IsPlayerConnected(playerid))
    {
        new vID = GetPlayerVehicleID(playerid), string[142], string2[3], Float:rotation, Float:vhealth;
        GetVehicleZAngle(vID, rotation);
        GetVehicleHealth(vID, vhealth);
        new direction = floatround(rotation, floatround_round);
        while(direction > 360) direction -= 360;
        while(direction < 0) direction += 360;
        switch(direction)
        {
            case 0 .. 22, 338 .. 360: string2 = "N";
            case 23 .. 67: string2 = "NW";
            case 68 .. 112: string2 = "W";
            case 113 .. 157: string2 = "SW";
            case 158 .. 202: string2 = "S";
            case 203 .. 247: string2 = "SE";
            case 248 .. 292: string2 = "E";
            case 293 .. 337: string2 = "NE";
        }
        format(string, sizeof(string), "~w~VEHICLE: ~y~%s~n~~w~SPEED: ~y~%d KM/H~n~~w~LOCATION: ~y~%s~n~~w~DIRECTION: ~y~%s~n~~w~HEALTH: ~y~%0.0f%s", VehicleNames[GetVehicleModel(vID) - 400], GetPlayerSpeed(playerid), GetPlayerArea(playerid), string2, vhealth, "%%");
        TextDrawSetString(VehicleInfo[playerid], string);
        TextDrawShowForPlayer(playerid, VehicleInfo[playerid]);
        string = "\0";
    }
    else
    {
        KillTimer(VehicleTimer[playerid]);
        TextDrawHideForPlayer(playerid, VehicleInfo[playerid]);
        TextDrawHideForPlayer(playerid, VehicleBox[playerid]);
    }
    return 1;
}

public OnPlayerStateChange(playerid, newstate, oldstate)
{
    if(newstate == PLAYER_STATE_DRIVER || newstate == PLAYER_STATE_PASSENGER)
        VehicleTimer[playerid] = SetTimerEx("SpeedometerUpdate", 1000, true, "i", playerid);
    if(newstate == PLAYER_STATE_ONFOOT && (oldstate == PLAYER_STATE_PASSENGER || oldstate == PLAYER_STATE_DRIVER))
        KillTimer(VehicleTimer[playerid]);
    return 1;
}
Quote:
Originally Posted by ******
Посмотреть сообщение
I mean that if you use multiple timers, there is a loop over them somwhere internally in the server. If you use one timer, the loop is in your code. Either way - there is a loop to call the same chunk of code (the main loop body) multiple times. People seem to think that moving the loop in to your code is a good thing because the server (which is written in C++ BTW, not PAWN) is somehow bad at loops and anyone can do better in 3 seconds of PAWN. WHY people think this, I don't know!
Alright, thanks!

Quote:
Originally Posted by Bakr
Посмотреть сообщение
If you have only one timer (execution time is obviously exaggerated):
Код:
Player sync
Timer called (exec time = 5 seconds)
Timer ends > players go without sync for 5 seconds
Player sync
If you have a single big timer you may experience lag because while it is executing the players cannot sync. However, if you have multiple smaller ones, it chops it up to where players can sync between calls.
Код:
Player sync
Small Timer called (exec time = 1 sec)
Small Timer ends > players go without sync for 1 second
Player sync
Small Timer2 called (exec time = 1 sec)
Small Timer2 ends > players go without sync for 1 second
Player sync
...
This is because we only have a single thread to work with (which I use to look at as a disadvantage).
Thanks, that taught me a lot!
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)