Schnellste Dateiverarbeitung für PAWN

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
  • Vorwort:


    Man sieht ja die Performence von SII.
    Viele denken, schneller geht's garnicht mehr.
    Doch das ist falsch.
    Deshalb möchte ich nun einigen zeigen, wie schnell eine Dateiverarbeitung sein kann.


    Wie funktioniert dies?


    Es werden die Daten nicht mehr als für den Menschen lesbaren ASCII Code gespeichert, sondern nur ihre Bits.
    Das ist erheblich schneller auszulesen und zu schreiben.
    Man muss sich allerdings im klaren sein, das man die Daten mit es nurnoch per Script oder Hexeditor/Programm bearbeiten kann.


    Erläuterung des Systems


    In PAWN ist jede Variable 4 Byte groß.
    Somit verbraucht der Buchstabe a genauso viel Speicher wie die Zahl 26367343.


    Speicher wir diese Zahl nun als ASCII String, verbrauchen wir viele Byte.
    Und zwar für jede Ziffer 1 Byte.


    Dies wieder auszulesen dauert "zulange" für manche.
    Deswegen speichern wir die Zahl als 4 Byte ab.


    Grobe Funktion:


    Wichtig: io_readwrite ist verbugt und sollte NICHT verwendet werden.
    main()
    {
    new File:FileStream = fopen("test.txt", io_write);
    if(!FileStream) // prüfen ob die Handle/Stream okay ist
    {
    printf("Error");
    return;
    }

    new test[32], pos = 0; // Test Array + position (Hier 32, werden zwar nicht alle benötigt, aber es werden eh nur die benötigten geschrieben. ;)
    test[pos++] = 13534; // Stellen wir uns vor das ist das Spielergeld
    add_str("DMA", pos, test); // und das der Spielername

    fwrite(FileStream, test); // schreiben unserer "Userdaten"

    fclose(FileStream); // schließen da io_readwrite verbugt ist und wir jetzt io_read nutzen müßen.

    FileStream = fopen("test.txt", io_read);

    if(!FileStream) // selbe Prozedur wie oben
    {
    printf("Error");
    return;
    }

    fread(FileStream, test); // Wir lesen aus.

    printf("%d", test[0]); // Wir erhalten unser Geld ausgegeben.
    // schließen
    fclose(FileStream);
    }


    add_str(string[], &pos, write[], size_w = sizeof write)
    {
    for(new i = 0; i < strlen(string); i++, pos++)
    {
    if(pos < size_w)
    {
    write[pos] = string[i];
    }
    }
    }


    Bis zu 30 Nanosekunden schneller wäre strins, aber die 30NS merkt man eh nicht. ;)


    Schaut euch ruhig die test.txt nun an.
    Wie ihr seht, ist DMA noch vorhanden.
    Das hat damit zutun, das der String ja nur ein Array ist und jeder Buchstabe ein Array Feld ist.
    Außerdem seht ihr ein "Merkwürdiges" Zeichen vor DMA.
    Dies ist unsere Zahl. ;)


    Speichern eines Users:


    Hier ein Beispiel für ein sehr effektives Userdaten System:
    main()
    {
    new p_money = 6372, p_wantedlevel = 352323, p_houseid = 255;
    SaveUser("DMA", p_money, p_wantedlevel, p_houseid);
    p_money = 0, p_wantedlevel = 0, p_houseid = 0;
    // Nun müßen wir wieder die Daten holen
    ReadUser("DMA", p_money, p_wantedlevel, p_houseid);
    // Testen ob's geklappt hat:
    printf("Money: %d WantedLevel: %d HouseID: %d", p_money, p_wantedlevel, p_houseid);
    }


    SaveUser(name[], money, wantedlevel, houseid)
    {
    new msg[64], File:FileStream, pos = 0;
    format(msg, sizeof msg, "/userdata/%s.user", name);
    FileStream = fopen(msg, io_write);
    if(!FileStream)
    return 0; // Nicht beschreibbar
    // User Datei offen
    msg = "";
    msg[pos++] = money; // pos++ erhöht die Position
    msg[pos++] = wantedlevel; // wantedlevel
    msg[pos++] = houseid; // und die Haus Identifikation
    fwrite(FileStream, msg); // schreiben
    fclose(FileStream); // UserDatei geschlossen
    return 1; // beschrieben
    }


    ReadUser(name[], &money, &wantedlevel, &houseid)
    {
    new msg[64], File:FileStream;
    format(msg, sizeof msg, "/userdata/%s.user", name);
    FileStream = fopen(msg, io_read);
    if(!FileStream)
    return 0; // Nicht lesbar
    // User Datei offen
    fread(FileStream, msg); // lesen
    money = msg[0];
    wantedlevel = msg[1];
    houseid = msg[2];
    fclose(FileStream); // UserDatei geschlossen
    return 1; // lesbar
    }


    Abschluß


    Und wieder habt ihr was von DMA gelernt.
    Bei Problemen oder Fragen, einfach in den Thread schreiben.


    Einmal editiert, zuletzt von DMA ()

  • Schont die Resourcen, sehr nice.


    @LIl: SII ist zwar schnell aber mit dem normalen Datei Typ gehts schneller und so wie DMA es erklärt hat ist es sehr schnell.


    Ich persönlich nutz SII or DINI weil ich zu faul bin den ganzen kack zu schreiben ^^ , wobei ich mich doch wieder
    zum normalen gedreht hab

    Mfg. BlackFoX_UD_ alias [BFX]Explosion


  • Man muss sich allerdings im klaren sein, das man die Daten mit es nurnoch per Script oder Hexeditor/Programm bearbeiten kann.


    Welche Programme kämen dafür in Frage?

  • Eigendlich jedes.
    Selbst DisAsm'er wie IDA Pro/Olly Debugger.


    Einfach mal Hexeditor bei Google eingeben.
    Ansonsten geht es ja noch per Script.


    Pawn ließt es 4 Byte ein und bei C/C++ so:
    unsigned char x[4]; // 4 byte
    fread(FileStream, x, 4); // 4 byte gelesen
    int zahl = *(unsigned char*)&x;

  • Eine AMX Datei, automatisch?
    Beim Compilen wird eine AMX Datei erstellt.


    AMX steht für Abstract Machine eXecute.
    Die Ausführbaredatei für die Abstract Machine.


    Das ist die virtuelle Maschine auf der AMX läuft. (Welche durch PAWN generiert wird)


    Wenn du das jetzt nicht verstanden hast, nehm es einfach hin. *g*

  • PAWN und PAWNO sind zwei verschiedene Dinge.
    Ich kann euch keine Lösung sagen, ich würde sagen, es handelt sich um ein Bug von PAWNO.


    Ich selber benutze Quincy, das ist die Ur-IDE für PAWN, welche von den PAWN Entwicklern, bzw. "fans" erstellt wurde. ;)

  • Mal eine kleine Frage:


    Hier wird das ganze nur mit Integern aufgeführt. Wie kann man aber einen String, bsp. einen Namen, oder einen Floatwert laden?
    Auf die gleiche Art & Weise oder benötigt man dort eine andere Form?

  • Funktioniert auf die selbe Art und weise.


    Hier Beispiel für Strings:
    #include <a_samp>


    enum ScriptData
    {
    Money,
    WantedLevel,
    HouseId,
    Password[32]
    };


    main()
    {
    new p_money = 6372, p_wantedlevel = 352323, p_houseid = 255, Test[ScriptData];
    SaveUser("DMA", p_money, p_wantedlevel, p_houseid, "rrr");
    // Nun müßen wir wieder die Daten holen
    ReadUser("DMA", Test[Money], Test[WantedLevel], Test[HouseId], Test[Password], 32);
    // Testen ob's geklappt hat:
    printf("Money: %d WantedLevel: %d HouseID: %d Password: %s", Test[Money], Test[WantedLevel], Test[HouseId], Test[Password]);
    }


    SaveUser(name[], money, wantedlevel, houseid, pwd[])
    {
    new msg[64], File:FileStream, pos = 0;
    format(msg, sizeof msg, "/userdata/%s.user", name);
    FileStream = fopen(msg, io_write);
    if(!FileStream)
    return 0; // Nicht beschreibbar
    // User Datei offen
    msg[0] = '\0';
    msg[pos++] = money; // pos++ erhöht die Position
    msg[pos++] = wantedlevel; // wantedlevel
    msg[pos++] = houseid; // und die Haus Identifikation
    msg[pos++] = strlen(pwd);
    add_str(pwd, pos, msg);
    msg[pos] = '\0';
    fwrite(FileStream, msg); // schreiben
    fclose(FileStream); // UserDatei geschlossen
    return 1; // beschrieben
    }


    ReadUser(name[], &money, &wantedlevel, &houseid, pwd[], size_p = sizeof pwd)
    {
    new msg[64], backup[32], File:FileStream;
    format(msg, sizeof msg, "/userdata/%s.user", name);
    FileStream = fopen(msg, io_read);
    if(!FileStream)
    return 0; // Nicht lesbar
    // User Datei offen
    fread(FileStream, msg); // lesen
    money = msg[0];
    wantedlevel = msg[1];
    houseid = msg[2];
    format(backup, sizeof backup, "%s", msg[4]);
    get_str(backup, msg[3], pwd, size_p);
    fclose(FileStream); // UserDatei geschlossen
    return 1; // lesbar
    }


    get_str(getfrom[], len, string[], size_g = sizeof string)
    {
    new pos = 0;
    for(new i = 0; i < strlen(getfrom); pos++, i++)
    {
    if(pos < size_g)
    {
    string[pos] = getfrom[i];
    }
    else if(pos == len)
    break;
    }
    }


    add_str(string[], &pos, write[], size_w = sizeof write)
    {
    for(new i = 0; i < strlen(string); i++, pos++)
    {
    if(pos < size_w)
    {
    write[pos] = string[i];
    }
    }
    }


    In Zeile 16 wird die StrLen per Hand übertragen, das ist nur bei Enums nötig, bei Strings die nicht in einer Enum List verpackt sind fällt der Parameter weg. (Sizeof erkennt hier die Länge)


    @Lil One:
    Frag's im Thread, ich füg keine Freunde hinzu *g*

  • Was ich mich frage:


    Was ist schneller, MySQL oder die Technick von DMA ?

  • Meine, da keine Network Connection, keine Verarbeitung in einem Extra Programm statt findet, ...


    Aber MySQL Server kann man von überall ansprechen und sind einfacher in Websites einzubinden.


    Rein geschwindigkeits mäßig ist aber meins schneller. :>