Code Optimierung

Wichtiger Hinweis: Bitte ändert nicht manuell die Schriftfarbe auf schwarz sondern belasst es bei der Standardeinstellung. Somit tragt ihr dazu bei dass euer Text auch bei Verwendung unseren dunklen Forenstils noch lesbar ist!

Tipp: Ihr wollt längere Codeausschnitte oder Logfiles bereitstellen? Benutzt unseren eigenen PasteBin-Dienst Link
  • SetTimerEx("CheckSpeed",100,false,"i",playerid);


    Allein hier besteht schon Opitimierungsbedarf ! 10 Mal pro Sekunde ist definitiv zu viel, meiner Meinung nach kann ein Speedo auch alle 1-2 Sekunden aktualisiert werden, ist dann zwar nicht ganz so flüssig aber schont schonmal ungemein die Ressourcen bei mehreren Spielern.

  • bei onplayerconnect
    new ipp[16];
    GetPlayerIp(playerid,ipp,sizeof(ipp));
    SetPVarString(playerid, "GetIP", ipp);


    stock GetIP(pid)
    {
    new SpielerIP[16];
    GetPVarString(pid, "GetIP", SpielerIP, 16);
    return SpielerIP;
    }


    das selbe kann man auch mit dem namen machen, so ist der cod gleich wieder um eineige zeilen kürzer

  • hatte ich auch schon über legt aber das halte ich für unsinfoll da der ja noch kürzere zeitinterwalle hat es ging mir aber bei meiner bitte eher darum den code an sich zu optimieren da ab es z.B. etwas mit DistanceBetweenPlayer was ich nich verstanden hatte vlt. kann man das für einen Speedo so anwenden dass es einfach besser ist

  • floatsqroot(((speed_x * speed_x) + (speed_y * speed_y)) +(speed_z * speed_z)) * 136.6666666666666666667;


    das kannst du noch optimieren , schau am besten im englischen forum nach ;) , wie ich sehe hast du das eh aus dem englischen forum da hat einer was schlaues hingeschrieben, floatmul ist das Stichwort!

  • floatsqroot(((speed_x * speed_x) + (speed_y * speed_y)) +(speed_z * speed_z)) * 137;
    So z.B =D ne aber halt anstatt *137 den Timer kleineren Interval und dafür immer weniger mal nehmen bei mir ist es *25 ..

    Why do programmers always mix up Halloween and Christmas?
    Oct 31 == Dec 25

  • So, ich dachte das passt hier ganz gut rein. Ich hab mir grad mal ein paar gedanken gemacht wegen Timern un globalen variablen und hab da nu 2 fragen^^
    1. Nehmen sich PVars und normale Variablen performance mäßig was? Also das z.b PVars schneller/langsamer/ressourcen schonender/fressender sind etc?


    2. Je mehr timer gleichzeitig laufen, desto mehr ressourcen, das is ja klar. Aber was wenn ich jetzt z.b nur einen timer benutze, der jede sekunde ausgeführt wird, und dann jede sekunde eine variable hochzähle und wenn diese dann z.b 60 erreicht hat (60 sekunden = eine minute^^) dann halt meinen code ausführen lasse?
    Falls man nicht versteht was ich meine:
    new AntiCheatTimer = 0,
    SpielerStatsUpdateTimer = 0,
    SpielerSaveTimer = 0;

    public OnGameModeInit()
    {
    SetTimer("GlobalTimer",1000,true);//Alle 1 Sekunden
    }
    public GlobalTimer()
    {
    AntiCheatTimer++;
    SpielerStatsUpdateTimer++;
    SpielerSaveTimer++;
    if(AntiCheatTimer == 5)//5 Sekunden
    {
    //blabla anticheat code oder funktion oder was auch immer
    AntiCheatTimer=0;
    }
    if(SpielerStatsUpdateTimer == 120)//120 Sekunden = 2 Minuten
    {
    //blabla Spieler Update code oder funktion oder was auch immer
    SpielerStatsUpdateTimer=0;
    }
    if(SpielerSaveTimer == 360)//360 Sekunden = 5 Minuten
    {
    //blabla alle spieler speichern
    SpielerSaveTimer=0;
    }
    }
    Ist das jetzt Besser oder schlechter das so zu machen? Und warum?
    Wäre schön wenn jmd ne antwort darauf hätte^^


    Mfg.

    The fact is, I am right. And if you think I'm wrong, you are wrong.

  • do.de - Domain-Offensive - Domains für alle und zu super Preisen
  • PVars waren noch nie schneller als normale Variablen und werden es auch nie sein. Weiss auch nicht,
    wieso einige das behaupten oder glauben.
    PVars sind definitiv langsamer. Der Sinn hinter PVars ist es, Informationen überall zugänglich
    zu haben innerhalb verschiedener Scripte. Das war zwar vorher schon möglich get/setProperty, wurde
    aber eher wenig genutzt.


    PVars blähen außerdem nicht die AMX zusätzlich auf, nutzen dagegen mehr CPU wenn sie benutzt
    werden.Ist also ein Thema RAM vs CPU.


    Zu den Timern.Einen für alles zu nutzen, ist nicht optimal.Hab Ich vor paar Jahren aber auch gemacht.
    Es ist besser, wenn man für jede Funktion einen eigenen Timer erstellt.
    Dieser hat dann aber ein Intervall das sich nicht mit einen überschneiden kann.
    Anstatt ein Intervall von 1000ms nimmt man 997ms oder 1009ms ( Primzahlen ) . Der Unterschied
    ist so minimal, den wirst du niemals bemerken.
    Primzahlen nimmt man deshalb, weil sich so die Timer nie überschneiden werden.


    Es gibt einen Grund,wieso die sich am besten nicht überschneiden sollen.
    Das jetzt selber ausführlich zu erklären dauert mir zu lange, dazu gibt es einen super Post
    von Y_Less im offiziellen SA:MP Forum. Aber wie immer, finde Ich den Post nicht.
    Ich schau nochmal nach, ob Ich den finde.


    //Edit:
    Ein hoch auf die Suchfunktion,
    http://forum.sa-mp.com/showthread.php?t=61322

    Einmal editiert, zuletzt von Goldkiller ()

  • Nabend,
    was ich immer öfter sehe, ist dass für jede Anwendung von einem String ein neuer erstellt wird, wie z.B. hier (ist ein fiktives Beispiel)
    CMD:pm(playerid,params[])
    {
    new pID, msg[80];
    if(sscanf(params, "us",pID,msg))return SendClientMessage(playerid,COLOR_RED,"Benutze: /pm [ID Nachricht!");
    if(!IsPlayerConnected(pID))return SendClientMessage(playerid,COLOR_RED,"Kein Spieler mit angegebener ID Online");
    if (pID == playerid)return SendClientMessage(playerid,COLOR_RED,"Du kannst dir nicht selbst eine PM schicken!");
    else
    {
    new str[128], str2[128],sender[MAX_PLAYER_NAME], ThePlayer[MAX_PLAYER_NAME];
    GetPlayerName(pID,ThePlayer,sizeof(ThePlayer));
    GetPlayerName(playerid,sender,sizeof(sender));
    format(str,sizeof(str),"PM von %s:%s",sender, msg);
    SendClientMessage(pID,PM,str);
    format(str2,sizeof(str2),"PM an %s gesendet:%s", ThePlayer,msg);
    SendClientMessage(playerid, PM, str2);
    }
    return 1;
    }
    Klar, kann man so machen, ist aber nicht wirklich gut und resourcenschonend. :(
    Also: Was tun?
    - Man könnte die einzelnen Strings wiederverwenden und neu formatieren
    - sich informieren wielang der Name maximal sein kann ( momentan 20 Zeichen, in der Wiki stehts falsch ;) )

    (Habs mit einem Namen von 21 Zeichen probiert, und man sieht was passiert ist ;) )


    Also das ganze könnte dann so aussehen
    CMD:pm(playerid,params[])
    {
    new pID, msg[80];
    if(sscanf(params, "us",pID,msg))return SendClientMessage(playerid,COLOR_RED,"Benutze: /pm [ID Nachricht!");
    if(!IsPlayerConnected(pID))return SendClientMessage(playerid,COLOR_RED,"Kein Spieler mit angegebener ID Online");
    if (pID == playerid)return SendClientMessage(playerid,COLOR_RED,"Du kannst dir nicht selbst eine PM schicken!");
    else
    {
    new str[128],sender[20], ThePlayer[20];
    GetPlayerName(pID,ThePlayer,sizeof(ThePlayer));
    GetPlayerName(playerid,sender,sizeof(sender));
    format(str,sizeof(str),"PM von %s:%s",sender, msg);
    SendClientMessage(pID,PM,str);
    format(str2,sizeof(str2),"PM an %s gesendet:%s", ThePlayer,msg);
    SendClientMessage(playerid, PM, str2);
    }
    return 1;
    }
    Anstatt der Größe von 20 für die Namen könnte man auch MAX_PLAYER_NAME neu definieren, ist vermutlich bequemer ;)
    #undef MAX_PLAYER_NAME
    #define MAX_PLAYER_NAME 20
    Das ganze angewendet ;)
    #undef MAX_PLAYER_NAME
    #define MAX_PLAYER_NAME 20
    CMD:pm(playerid,params[])
    {
    new pID, msg[80];
    if(sscanf(params, "us",pID,msg))return SendClientMessage(playerid,COLOR_RED,"Benutze: /pm [ID Nachricht!");
    if(!IsPlayerConnected(pID))return SendClientMessage(playerid,COLOR_RED,"Kein Spieler mit angegebener ID Online");
    if (pID == playerid)return SendClientMessage(playerid,COLOR_RED,"Du kannst dir nicht selbst eine PM schicken!");
    else
    {
    new str[128],pname[MAX_PLAYER_NAME];
    GetPlayerName(pID,pname,sizeof(pname));
    format(str,sizeof(str),"PM von %s:%s",pname, msg);
    SendClientMessage(pID,PM,str);
    GetPlayerName(playerid,pname,sizeof(pname));
    format(str2,sizeof(str2),"PM an %s gesendet:%s",pname, msg);
    SendClientMessage(playerid, PM, str2);
    }
    return 1;
    }
    Ich hoffe ich konnte einige erleuchten :huh:

  • Du kannst dir den string pname sparen.
    Sieht dann folgendermaßen aus :



    CMD:pm(playerid,params[])
    {
    new pID, msg[80];
    if(sscanf(params, "us",pID,msg))return SendClientMessage(playerid,COLOR_RED,"Benutze: /pm [ID Nachricht!");
    if(!IsPlayerConnected(pID))return SendClientMessage(playerid,COLOR_RED,"Kein Spieler mit angegebener ID Online");
    if (pID == playerid)return SendClientMessage(playerid,COLOR_RED,"Du kannst dir nicht selbst eine PM schicken!");
    else
    {
    new str[128];
    GetPlayerName(pID,str,sizeof(str));
    format(str,sizeof(str),"PM von %s:%s",str, msg);
    SendClientMessage(pID,PM,str);
    GetPlayerName(playerid,str,sizeof(str));
    format(str,sizeof(str),"PM an %s gesendet:%s",str msg);
    SendClientMessage(playerid, PM, str);
    }
    return 1;
    }


    Nicht jeder, der sich für super hält, ist ein Superheld. :love:
    ------------------------------------------------------------------------------------------------

  • ist ein zitat von seite 2 ;)


    Ich hab mal durchgeschaut und keine antwort gefunden was den schneller ist?

  • Ich denke mal, beides ist gleich, da ja "#define ..." benutzt wird.
    In PWN schreibst du es zwar als "IsConnected"/"foreach" aber in AMX kommt es wieder als "new .. = ..; for(....)" vor.
    (soviel ich weiß, ist das so!)


    Falls du es nicht verstanden hast (bzw. ich es net erklären konnte), zeige ich dir das mit einem Beispiel:


    #define COLOR_GREY 0xFAFAFAFF


    Diese Zeile da wird benutzt, damit man sich nicht immer die Hexzahlen merken muss, und stattdessen ganz einfach "COLOR_GREY" schreibt.


    Wenn du es z.B. so benutzt:
    SendClientMessage(playerid, COLOR_GREY, "What is this? This is a pencil!");


    Wird es im AMX-Datei wieder so geschrieben:
    SendClientMessage(playerid,0xFAFAFAFF,"What is this? This is a pencil!");"


    [b]Kurz gesagt, ich denke es macht kein Unterschied,du kannst den ganzen Script volldefinieren aber es wird wieder kein unterschied machen.
    Aber ich bin mir nicht sicher.. ^^

  • Wollte hier nochmal was zum Namen einwerfen.
    Ich z.B. benutze es so..
    new SpielerName[MAX_PLAYERS][MAX_PLAYER_NAME];
    Bei OnPlayerConnect
    GetPlayerName(playerid, SpielerName[playerid], MAX_PLAYER_NAME);


    Jetzt kann man in jedem Befehl einfach folgendes tun:
    COMMAND:kick(playerid,params[])
    {
    new pID, str[128];
    if(sscanf(params, "uz",pID,str))return SendClientMessage(playerid,0xC8C8C8FF,"/kick [ID/Name] [Grund]");
    if(!IsPlayerConnected(pID))return SendClientMessage(playerid,0xC8C8C8FF,"Dieser Spieler ist nicht online!");
    if (pID == playerid)return SendClientMessage(playerid,0xC8C8C8FF,"Du kannst dich nicht selber kicken!");
    if(pInfo[playerid][AdminLevel] > 1)
    {
    new str2[128];
    format(str2,sizeof(str2),"%s wurde vom Server gekickt! Grund: %s",SpielerName[pID],str[0] ? str : "Kein Grund");
    SendClientMessageToAll(0xFF6347AA,str2);
    Kick(pID);
    }
    else return SendClientMessage(playerid, 0xC8C8C8FF, "Dein Adminrank reicht nicht aus!");
    return 1;
    }


    Der Name kann nun immer und überall per
    SpielerName[playerid]
    ausgegeben werden.


    Also so mache ich das mit den Namen. Vielleichts hilfts ja weiter oder gibt es noch eine effizientere Methode, die
    ich evtl. überlesen habe?


    */Edit
    Sorry, für's Thread ausgraben, dachte es hilft evtl. mal weiter.
    Spart ja immerhin mehrere Zeilen ein.

  • Entnommen aus dem Tips & Tricks Thread von Slice aus dem englischen Forum.


    Ein normales Array kann werte zwischen -2,147,483,648 und 2,147,483,647 enthalten. Da aber z.b ein Array in der z.b die playerid eines Spielers gespeichert werden soll nie im leben so einen hohen/negativen wert haben wird, kann man dafür ein Char Array benutzen.
    Char Arrays können nur werte zwischen 0 und 255 enthalten (keine negativen werte, -1 wird automatisch zu 255). Also wenn man genau weiss, das der Wert des Arrays nicht weniger als 0 und nicht mehr als 255 sein wird, warum dann nicht ein bisschen Sparen?
    new bool:g_IsPlayerSomething[ MAX_PLAYERS ]; // Zellengröße 500 * 4 bytes pro zelle = 2000 bytes!
    new bool:g_IsPlayerSomething[ MAX_PLAYERS char ]; // 500 bytes = .. 500 bytes!


    Aber: Bei der verwendung von Char Arrays muss man geschweifte klammern anstatt Eckigen klammern verwenden
    public OnPlayerConnect( playerid )
    {
    g_IsPlayerSomething{ playerid } = false;
    // ^ ^
    }


    public OnPlayerSpawn( playerid )
    {
    // v v
    if ( g_IsPlayerSomething{ playerid } )
    {
    // ..
    }
    }

    The fact is, I am right. And if you think I'm wrong, you are wrong.