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
  • new FALSE = false;
    #define SendFormattedMessage(%0,%1,%2) do{new _str[128]; format(_str,128,%2); SendClientMessage(%0,%1,_str);}while(FALSE)

    SendFormattedMessage(playerid,color,"Du hast %s SkinID %d zugewiesen",SpielerName[pID],sID);


    Spart das lästige erstellen von Strings und Formatierungen.


    */Edit: Funktion ist nicht von mir. Stammt, soviel ich weiß aus dem Englischen SA:MP Forum.

  • totaler schwachsinn. so hat jeder string 128 zeichen. egal ob ich 2 oder 500 zeichen brauche...


    desweiteren wird jedesmal ne neue variable erstellt.
    wenn man 2 texte hinternander sendet, kann man die variable 2mal nutzen

  • ich bin höflich? 8|


    hier geht es aber um code optimierungen => kinder die das nicht kennen denken "wooow wie geil voll geil ey, junge" und da kann ich nur eins zu sagen: "leider nein, leider garnicht"


    ich zeige nur, dass dein code nicht in code optimierung passt. wenn dus in codeschnippsel gepostet hättest, würd ich ja nix sagen. aber hier ist das dumm :D

  • new i, l = strlen( string )
    for (; i != l; i++ )
    {
    //Code
    }
    die schnellste Möglichkeit, die ICH kenne um durch einen String zu "kommen"

    "Bevor ich mir Informationen aus der "Bild" hole,
    werde ich anfangen, Wahlergebnisse danach vorauszusagen,
    neben welchen Busch unsere Katze gepinkelt hat."

    Margarete Stokowski

  • do.de - Domain-Offensive - Domains für alle und zu super Preisen
  • Denk ich ma, da sonst der Code noch einmal prüfen müsste, ob die Var auch wirklich kleiner ist, also ungleich und kleiner das sind 2 Dinge, und so muss er nur Prüfen ob es ungleich ist

    "Bevor ich mir Informationen aus der "Bild" hole,
    werde ich anfangen, Wahlergebnisse danach vorauszusagen,
    neben welchen Busch unsere Katze gepinkelt hat."

    Margarete Stokowski

  • Ist es, ich hab gerade mal nen kleinen Speedtest gemacht:


    public OnFilterScriptInit()
    {
    print("\n--Base FS loaded.\n");

    new x=0, y=1, time,time2, z=0;
    time=GetTickCount();
    for(new i=0;i<10000000;i++)
    {
    if(x<y) z++;
    }
    time2=GetTickCount();
    printf("Dauer KLEINER: %i",time2-time);

    for(new i=0;i<10000000;i++)
    {
    if(x!=y) z++;
    }
    printf("Dauer Ungleich: %i",GetTickCount()-time2);
    return 1;
    }


    Dauer Kleiner: 2150
    Dauer Ungleich: 1950


    Obwohl man den Unterschied bei einem (!) Durchlauf überhaupt nicht bemerken kann, hier waren es 200ms Unterschied bei 10 Millionen Durchläufen.

  • 200ms bei 10kk Durchgängen ist wenig. Ein Durchschnittsstring hat 256 Zeichen.
    Das wären meiner Rechnung nach 0,0511 Millisekunden Unterschied.

    Kalcor: "... it makes the game look like it's not GTA. This mod is called San Andreas Multiplayer. It's not a custom game engine which you can script..."

  • Ich hab her noch eine kleine Optimierungsmöglichkeit für Schleifen :)


    Meine Theorie:
    Eine While Schleife ist schneller als eine For Schleife


    Der Grund:
    In einer For Schleife muss (zwar nicht zwingend) er die variable erstellt werden, dann wird die Bedingung überprüft und am Ende der Schleife wird die Var erhöht und die Bedingung erneut geprüft.
    Die While schleife spart sich die ganzen Schritte von hochzählen und var erstellen,sSie überprüft nur die Bedingung.
    Var erstellen ist vorher und die var hochzählen ist mittendrin möglich.


    Der Beweis:
    Ich hab den Test mit 1000000 Wiederholungen gemacht und dieses Ergebnis erhalten
    Eine while schleife ist 2x so schnell wie eine for schleife und eine do while schleife etwas langsamer(manchmal auch schneller, wie bei mir gerade der Fall :S ) als eine while schleife


    1.Testergebnis


    while Loop 10037ms
    for Loop 20457ms
    do while 10218ms


    2.Testergebnis


    while Loop 10168ms
    for Loop 20645ms
    do while 9971ms


    Code für den Test hier: http://pastebin.com/iyfBCQG2


    Die Optimierung:
    Aus
    for(new i;i<MAX_PLAYERS;i++)
    {
    //iwas
    }
    machen wir ganz einfach
    new i;
    while(i<MAX_PLAYERS)
    {
    //iwas
    i++; // wichtig ist das hier die var um eins hochgesetzt wird sonst ende die Schleife nie :P
    }
    oder
    new i;
    do
    {
    //iwas
    i++; // wichtig ist das hier die var um eins hochgesetzt wird sonst ende die Schleife nie :P
    }
    while(i<MAX_PLAYERS); // wichtig² hier muss ein ; stehen
    und für die geschwindigkeit Junkies unter uns :D
    new i;
    while(i!=MAX_PLAYERS)
    {
    //iwas
    i++; // wichtig ist das hier die var um eins hochgesetzt wird sonst ende die Schleife nie :P
    }
    //und
    new i;
    do
    {
    //iwas
    i++; // wichtig ist das hier die var um eins hochgesetzt wird sonst ende die Schleife nie :P
    }
    while(i!=MAX_PLAYERS); // wichtig² hier muss ein ; stehen


    //Edit: 1.Testergebnis & 2. Testergebnis

    "Bevor ich mir Informationen aus der "Bild" hole,
    werde ich anfangen, Wahlergebnisse danach vorauszusagen,
    neben welchen Busch unsere Katze gepinkelt hat."

    Margarete Stokowski

  • Leider ist der Test nicht richtig aufgebaut bzw du hast nicht überall die gleichen Vorraussetzungen.


    http://pastebin.com/iyfBCQG2

    • Lediglich in der for() Schleife erstellst du immer eine neue Variable l , anstatt wie bei while() und do-while() k zu verwenden.
    • Bei der for() Schleife werden 2. Variablen inkrementiert, l und k. Dabei hat k wie in Punkt1 genannt nichts mit der for() Schleife zu tun.


    Das sind Beides Nachteile für die for() Schleife.


    Zitat

    --- Unten 5x Durchläufe ---


    Hier mein Code.
    http://pastebin.com/AJh01BBj
    //Edit:
    Pastebin war falsch :-X


  • Ich meine damit sowas wie hier: Link
    Wie arbeitet man damit richtig? Wo soll es benutzt werden?
    Ist es immer nützlich? Arbeitet das Programm schneller damit?


    Auf Frage von ioRawr, versuche ich mal den Code zu erklären.
    Es ist definitiv nichts für PAWN Anfänger bzw allg. Anfänger im Coding Bereich.


    Übrigens, in dem Code fehlt eine Zeile. "return model" muss noch eingefügt werden,sonst bringt die Funktion nichts.
    stock GetVehicleSeatCount(model)
    {
    static const
    scMaxPassengers[] =
    {
    0x10331113, 0x11311131, 0x11331313, 0x80133301, 0x1381F110, 0x10311103, 0x10001F10, 0x11113311, 0x13113311,
    0x31101100, 0x30001301, 0x11031311, 0x11111331, 0x10013111, 0x01131100, 0x11111110, 0x11100031, 0x11130221,
    0x33113311, 0x11111101, 0x33101133, 0x101001F0, 0x03133111, 0xFF11113F, 0x13330111, 0xFF131111, 0x0000FF3F
    };
    if (400 <= model <= 611)
    {
    model -= 400;
    model = (scMaxPassengers[model >>> 3] >>> ((model & 7) << 2)) & 0xF;
    if (model == 15)
    {
    return -1;
    }
    return model; // <---
    }
    else
    {
    return -1;
    }
    }

    Erstmal die Vorbereitung.Was haben wir eigentlich?
    Wir haben 611 - 400 Fahrzeuge.Sind also 211 Fahrzeuge, für die wir Werte speichern müssen.
    Es gibt kein Fahrzeug,dass mehr als 8 Sitzplätze hat ( Bus , 8 + Fahrer ). Damit wir die Zahl 8 in Binär darstellen können,
    müssen wir 4 bits verwenden.Denn 8 = 0b1000 . Die höchste Zahl die wir daher darstellen könnte wäre theoretisch 15 in diesem Fall.
    Ist aber sowieso nicht möglich,denn sonst hätten wir keine 8 als höchsten Wert für Sitzplätze genommen.
    Y_Less verwendet aber die 15 als Spezialfall,bedeutet, dass Fahrzeug bietet überhaupt keine Sitzmöglichkeit ( Weder Fahrer,noch
    Beifahrer ). Dazu später mehr.
    Bisher haben wir also herrausgefunden,dass wir eigentlich nur 4 bits benötigen pro Fahrzeug und das 211 mal. Macht Insgesamt 844 bits,
    um alle Informationen darzustellen.


    Da eine Variable ( Cell ) in PAWN 4 Byte hat ( 32 bits ) , können wir pro Variable also 8 ( 32 bits / 4 bits ) Sitzplätzwerte verwalten.
    Daraus resultiert,wir haben 8 Blöcke mit jeweils 4 bits pro Variable. Ich nenne diese einfach mal 4 bit-Block im weiteren Verlauf.


    Wie wir sehen,Y_Less hat 27 Variablen ( Code basiert allerdings auf einen Post von RyDeR` ) bzw ein Array mit einer
    Größe von 27.
    Genau genommen ist 211 / 8 = 26,375 . Wir können aber keine 0,375 Variablen erstellen, müssen daher aufrunden. Daher auch 27. Kann man
    auch überprüfen durch 26 * 32 bit , sind nur 832 bits.Wir vorher errechnet,wir brauchen aber 844 bits.


    Im ersten Schritt müssen wir herrausfinden, in welcher Variablen ( genau genommen, welcher Index ) der Wert für unser Fahrzeug
    steckt.
    Das geschiet hier:
    model -= 400;
    model >>> 3
    Da die Fahrzeuge erst bei 400, verschieben wir den Anfang zuerst. Wir verschieben alle ModelIDs um 400 nach unten.
    Sonst wären die ersten 400 Werte nutzlos ( 0 - 399 ) , da wir für diese keine Werte benötigen.Es gibt nämlich keine Fahrzeuge
    mit diesen ModelIDs.
    Gehen wir eine Zeile weiter ( model >>> 3 ).
    Ist in diesem Fall nichts Anderes als die Berechnung model / 8. Die 8 kommt von den 8 Sitzplatzwerten pro Variable.


    Angenommen für die modelid 411.
    411 -= 400;
    11 >>> 3 = 1
    Gut,wir wissen, dass der Wert für ModelID 411 in Index 1 steckt.


    Zitat

    400 - 407 ( 0 )
    408 - 415 ( 1 )
    416 = 423 ( 2 )
    424 = 431 ( 3 )
    ...


    scMaxPassengers[1] = 0x11311131 = 0b00010001001100010001000100110001 = 0001 0001 0011 0001 0001 0001 0011 0001
    Die Farben sind nur zur Verdeutlichung.Ich habe auch einfach mal den Block Fett markiert,den wir später suchen.




    Als nächstes müssen wir herrausfinden, in welchem der 4 bit-Blöcke der Wert steckt, den wir suchen.Das passiert hier:
    ((model & 7) // model & 0b111
    In unserem Fall würde es so aussehen:
    (( 11 & 7 ) // (( 0b1011 & 0b0111 )
    Das Ergebnis daraus ist 3 ( 0b1011 & 0b0111 ). Man hätte an dieser Stelle auch den Rest der Rechnung 11 durch 8 nehmen können.Ergibt ebenfalls
    3 und steht für "Wieviele 4 bit-Blöcke müssen wir verschieben,um den gesuchten an vorderster Position zu haben".
    In PAWN wäre es übrigens 11 % 8 ( = 3 ).


    Wir haben jetzt also den 4 bit-Block gefunden,den wir benötigen.Er ist in der Variable bei Index 1 und dort der vierte 4 bit-Block.
    Um an den vierten 4 bit-Block zu kommen,müssen wir den 4 bit-Block 3 Blöcke nach vorne schieben, bzw nach Rechts ( >> ).Das nennt sich Bit-Shiften.
    Denn wir beginnen hier bei den Blöcken bei 0 zu zählen.Der 1 4 bit-Block wird nämlich nicht ( also 0 mal ) geshiftet, ist nämlich schon an Vorderster Stelle.
    Der 2 4 bit-Block muss um 1 geshiftet werden,damit er an vorderster stelle steht.
    Der 3 " " " 2 geshiftet ","
    usw usf


    Jetzt sind wir bei folgendem Teil. Denn wir müssen zuerst Klammern berechnen.
    ((model & 7) << 2))
    Wir wissen ja, dass wir es um 3 4 bit-Blöcke verschieben müssen,damit der Gesuchte 4 bit-Block am Anfang steht. Da ein 4 bit-Block nun mal aus 4 Bits besteht,müssen wir alles um
    3 * 4 Bits verschieben. Das * 4 ist in diesem Fall << 2 , ist identisch .( << 1 wäre * 2 )
    Das würde Binäir so aussehen:

    Ausgang: 0001 0001 0011 0001 -> 0001 <- 0001 0011 0001
    Ergebnis: 0001 0011 0001 0001 0001 0011 0001 -> 0001 <- // Achtung , >> ist nicht >>> ! Macht in diesem Fall aber keinen Unterschied


    Jetzt haben wir den 4 bit-Block den wir benötigen an die vordersten 4 bits der Variablen verschoben. Damit wir auch nur diesen 4 bits bekommen,
    müssen wir jetzt & 0b111 machen.Dadurch fallen alle bits weg, die wir nicht benötigen.
    Für unseren Fall:
    0b0001 & 0b1111 = 0b0001 = 1.
    Damit wissen wir jetzt entgültig, dass wir 1 Sitzplatz für Fahrzeug 411 haben,neben dem Fahrersitz. Ein Spezialfall ist 15. Hätten wir jetzt also 15 als Lösung bekommen, wüssten wir, dass es eigentlich gar keine Sitzmöglichkeit für diese ModelID gibt. Es ist ein Sonderfall. 15 ist auch gleichzeitig der höchste Wert den wir mit 4 bits darstellen können ( Vorzeichenfrei ) .
    Man könnte auch anstatt die 15 eine eine Andere Zahl nehmen. Es wäre irgendeine Zahl zwischen 9 und 15 möglich,da wir ja wissen,dass kein Fahrzeug einen gültigen Wert über 8 hat.


    Was haben wir denn jetzt eigentlich davon ? Wir nutzen wenig Speicher, oder für einige Experten ... die AMX wird nicht so groß ( Was sowieso noch nie ein gute Kriterium war ).


    Ergebnis:
    Die oben gezeigte Variante verbraucht nur 27 * 4 byte , macht also 107 byte ( Technisch werden nur 211 ( Fahrzeuge ) * 4 ( bits ) 844 bits je benutzt).
    Würden wir einen Wert pro Variable benutzen, dann hätten 211 byte = 844 byte.
    Macht also 107 byte vs 844 byte. Um es mal in Prozent auszudrücken. Die oben gezeigte Variante belegt nur 12.6% von dem Speicher, den die normale Methode verbrauchen würde.Oder auch anders, die normale Methode ist um 788% Größer was den Speicherbedarf betrifft.



    Puh... so viel geschrieben, dachte das wird kürzer. Vorraussetzung dafür,dass man es versteht, sind Grundzüge des Binärsystems ( & ; << ; >> ). Sonst wird es mit dem verstehen sicherlich nicht auf anhieb klappen. Ich hoffe ich habe da jetzt nicht totalen Blödsinn geschrieben, so viele 0 und 1 ... :pinch:



    //Edit:
    Im übrigen verwende ich das ab und zu.Hier mal ein Beispiel, wie man Waffe + Munition in 1 Variable speichern kann.
    stock Class_CompressWeaponInfo(weaponid,ammo) {
    new
    info;
    info = ( ammo << 7 ) | weaponid;
    return info;
    }

  • Uhuhu nice erklärt ;)
    Ich habe es nur nicht ganz verstanden. Aber naja, da ich mit Sitzplätzen im Moment nicht arbeite, brauch ich das wohl auch nicht so ^^

    Unkompetent. Das neue dynamisch.



    ihr seit schon lustig postet erros aber nicht die zeilen wo sie sind dann können wir euch auch nicht helfen^^


    Lernt Scripten, Leute, und macht eure Augen auf!


    _______________________________________
    50 Beiträge: [x] 300 Beiträge: [x]
    100 Beiträge: [x] 500 Beiträge: [x]
    150 Beiträge: [x] 1000 Beiträge: [x]
    200 Beiträge: [x]
    2000 Beiträge: []
    250 Beiträge: [X] Boardaktivitäten: Profil


    [size=36]_______________________________________

    /Edit: Schmerzt es dir eigentlich nicht so ein Müll zu schreiben 8|

  • So steig ich auch ma ein.

    #define DIALOGTEXT "blabla\nblabla\nblalblalba"



    könnt ihr nun als string benutzen..


    ShowPlayerDialog(....."Überschrift",DIALOGTEXT, "Oke","Abbrechen");


    Ebenso mit normalem String.


    Zahlen kann man auch verwenden.


    #define max 32
    #define min 1


    if(max <= 32)
    {
    Ausführen wenn Max untergleich 32 ist
    }


    zur absicherung


    if(max <= 32 && min >= 1)


    Das selbe Spiel mit min...



    Das gesammte Forum voller *Doppelzensierung hält einen vom Stress zugemüllt, da blickt man gar nimma durch.

  • Uhuhu nice erklärt ;)
    Ich habe es nur nicht ganz verstanden. Aber naja, da ich mit Sitzplätzen im Moment nicht arbeite, brauch ich das wohl auch nicht so ^^


    Ich denke es geht auch nicht um den Sinn hinter der Funktion. Ich nehme an,dass ioRawr eher wissen wollte was dort konkret passiert und wieso es so überhaupt funktioniert. Allgemein sind Bit-Operationen sehr praktisch. Beispielsweise bei gPM nutz ich es um den Status von Nachrichten zu verwalten.Mit 1 Variable kann ich 3 Informationen Abfragen.
    enum ( <<= 1 ) {
    MessageStatus_Read = 1,
    MessageStatus_DEL_Sender, // del von sender ( postausgang )
    MessageStatus_DEL_Empfaenger // del von empfaenger ( posteingang )
    }


    Genug ausgeführt, schweife sonst zu sehr vom Thema ab. Sollte das vllt eher in ein Tutorual schreiben :wacko: