khalidahmedshalabi / SAMPBulletproof

Bulletproof Gamemode is a SA-MP gamemode which is believed to take A/D and TDM to a new level.
http://khalidahmedshalabi.github.io/BulletproofGamemodeWebsite/
Apache License 2.0
16 stars 20 forks source link

Lag issue (on/after player connected to the server) #17

Closed khalidahmedshalabi closed 9 years ago

khalidahmedshalabi commented 9 years ago

There's noticeable lag (server freezes for 0.5 to 2 seconds most of the times) when a player connects. This needs investigation, however I guess it's the GetPlayerCountry; @Whitetigerswt must know more about this since he's the one who developed it.

A-Gebrel commented 9 years ago

https://youtu.be/Tp5YMxUYYfM

First is a host on my vps, second is localhost. There's a difference in speed but not sure if it's geoip.

khalidahmedshalabi commented 9 years ago

Well, this means our testing should not be done on home hosts. Run this on the same vps @ApplePieLife:

public OnPlayerConnect(playerid)
{
    printf("OnPlayerConnect(%d): init", playerid);
    new tick = GetTickCount();
    // Check if version is out-dated and if server owners are forced to use newest version
    if(VersionReport == VERSION_IS_BEHIND && ForceUserToNewestVersion == true)
    {
        SendClientMessageToAll(-1, sprintf(""COL_PRIM"Version checker: {FFFFFF}the version used in this server is out-dated. You can visit "COL_PRIM"%s {FFFFFF}to get the latest version", GM_WEBSITE));
        SendClientMessageToAll(-1, sprintf(""COL_PRIM"Server version: {FFFFFF}%s "COL_PRIM"| Newest version: {FFFFFF}%s", GM_NAME, LatestVersionStr));
        SetTimerEx("OnPlayerKicked", 500, false, "i", playerid);
        return 0;
    }
    printf("OnPlayerConnect(%d): Version check: took approx. %d ms since last print", playerid, GetTickCount() - tick);
    tick = GetTickCount();
    if(DatabaseLoading == true)
    {
        ClearChatForPlayer(playerid);
        SendClientMessage(playerid, -1, "Please wait! Database loading, you will be connected when it's loaded successfully.");
        SetTimerEx("OnPlayerConnect", 1000, false, "i", playerid);
        return 0; // If database is still loading, disable the player from spawning
    }
    printf("OnPlayerConnect(%d): Database load check: took approx. %d ms since last print", playerid, GetTickCount() - tick);
    tick = GetTickCount();
    // Check if players count exceeded the limit
    if(Iter_Count(Player) == MAX_PLAYERS)
    {
        SendClientMessageToAll(-1, sprintf(""COL_PRIM"ID %d could't connect to the server properly. Maximum players limit exceeded!", playerid));
        SendClientMessageToAll(-1, sprintf("MAX PLAYERS LIMIT: %d | Ask for a special and increased limit | %s", MAX_PLAYERS, GM_WEBSITE));
        SetTimerEx("OnPlayerKicked", 500, false, "i", playerid);
        return 0;
    }
    printf("OnPlayerConnect(%d): Players limit check: took approx. %d ms since last print", playerid, GetTickCount() - tick);
    tick = GetTickCount();
    // Send them welcome messages
    SendClientMessage(playerid, -1, ""COL_PRIM"It's {FFFFFF}Bulletproof"COL_PRIM". Your bullets are fruitless. You can't take it down!");
    SendClientMessage(playerid, -1, ""COL_PRIM"Get started: {FFFFFF}/help "COL_PRIM"and {FFFFFF}/cmds");
    SendClientMessage(playerid, -1, ""COL_PRIM"Don't miss our updates: {FFFFFF}/checkversion");
    SendClientMessage(playerid, -1, ""COL_PRIM"Check {FFFFFF}/changelog "COL_PRIM"out to see what's up with this version!");
    SendClientMessage(playerid, -1, ""COL_PRIM"Developers: {FFFFFF}Whitetiger"COL_PRIM" & {FFFFFF}[KHK]Khalid"COL_PRIM"");
    printf("OnPlayerConnect(%d): welcome message: took approx. %d ms since last print", playerid, GetTickCount() - tick);
    tick = GetTickCount();
    new str[128];
    format(str,sizeof(str),""COL_PRIM"Server limits:  Min FPS = {FFFFFF}%d "COL_PRIM"| Max Ping = {FFFFFF}%d "COL_PRIM"| Max PL = {FFFFFF}%.2f", Min_FPS, Max_Ping, Float:Max_Packetloss);
    SendClientMessage(playerid, -1, str);
    printf("OnPlayerConnect(%d): server limit message: took approx. %d ms since last print", playerid, GetTickCount() - tick);
    tick = GetTickCount();

    // Initialize the new player
    InitPlayer(playerid);
    printf("OnPlayerConnect(%d): InitPlayer: took approx. %d ms since last print", playerid, GetTickCount() - tick);
    tick = GetTickCount();
    #if defined _league_included
    CheckPlayerLeagueRegister(playerid);
    #endif
    CheckPlayerAKA(playerid);
    printf("OnPlayerConnect(%d): AKA check: took approx. %d ms since last print", playerid, GetTickCount() - tick);
    tick = GetTickCount();

    // Tell everyone that he's connected
    str = "";
    GetPlayerCountry(playerid, str, sizeof(str));
    printf("OnPlayerConnect(%d): GetPlayerCountry: took approx. %d ms since last print", playerid, GetTickCount() - tick);
    tick = GetTickCount();
    format(str, sizeof(str), "{FFFFFF}%s {757575}(ID: %d) has connected [{FFFFFF}%s{757575}]", Player[playerid][Name], playerid, str);
    SendClientMessageToAll(-1, str);
    printf("OnPlayerConnect(%d): Connected message: took approx. %d ms since last print", playerid, GetTickCount() - tick);

    if(AllMuted) // If everyone is muted (global mute, /muteall?), this player should be muted too
        Player[playerid][Mute] = true;
    return 1;
}
A-Gebrel commented 9 years ago
[22:50:41] OnPlayerConnect(0): init
[22:50:41] OnPlayerConnect(0): Version check: took approx. 0 ms since last print
[22:50:41] OnPlayerConnect(0): Database load check: took approx. 0 ms since last print
[22:50:41] OnPlayerConnect(0): Players limit check: took approx. 0 ms since last print
[22:50:41] OnPlayerConnect(0): welcome message: took approx. 0 ms since last print
[22:50:41] OnPlayerConnect(0): server limit message: took approx. 0 ms since last print
[22:50:41] OnPlayerConnect(0): InitPlayer: took approx. 0 ms since last print
[22:50:41] OnPlayerConnect(0): AKA check: took approx. 0 ms since last print
[22:50:41] OnPlayerConnect(0): GetPlayerCountry: took approx. 1 ms since last print
[22:50:41] OnPlayerConnect(0): Connected message: took approx. 0 ms since last print

@KHKKhalid Doesn't really seem to lag.

khalidahmedshalabi commented 9 years ago

You got this result and the game still lagged when you connected (like the video), @ApplePieLife? If so, it's likely not OnPlayerConnect then.

khalidahmedshalabi commented 9 years ago

It's the login code under OnPlayerRequestClass then I guess. Could you benchmark and test it on your VPS again @ApplePieLife? Here's a sample code...

printf("Player logged-in status: %b", Player[playerid][Logged]);
new tick = GetTickCount();
if(Player[playerid][Logged] == false)
{
....
....
....
}
printf("Login code took approx. %d ms", GetTickCount() - tick);
A-Gebrel commented 9 years ago
[16:51:00] [join] ThatBoyCBUG148 has joined the server (0:HIDDEN)
[16:51:00] START:ForgetSpectator(0)
[16:51:00] END:ForgetSpectator(0)
[16:51:01] Player logged-in status: 0
[16:51:01] Login code took approx. 0 ms
[16:51:08] START:StopSpectate(0, 1)
[16:51:08] [part] ThatBoyCBUG148 has left the server (0:1)

Well, I'm not sure if you edited anything with login codes but I've noticed it's way faster now. (( or we both simply had bad ping in that day ))

khalidahmedshalabi commented 9 years ago

Some general benchmarking...

[22:34:49] Login code took approx. 5060 ms to execute
[22:34:49] SpawnConnectedPlayer code took approx. 0 ms to execute
[22:37:22] Login code took approx. 4422 ms to execute
[22:37:22] SpawnConnectedPlayer code took approx. 0 ms to execute

It is the login code. I'll probably add more benchmarks to find the root of this lag/delay later.

Whitetigerswt commented 9 years ago

don't waste your time with old benchmarking? https://github.com/Zeex/samp-plugin-profiler

https://www.youtube.com/watch?v=LjHo1CZ-h8w

khalidahmedshalabi commented 9 years ago

Found it! It's this code under LoginPlayer

// Update players table with new IP address for auto login if they reconnect.
format(iString, sizeof(iString), "UPDATE `Players` SET `IP` = '%s' WHERE `Name` = '%s'", IP, Player[playerid][Name]);
db_free_result(db_query(sqliteconnection, iString));