Szerző Téma: String Takarékosság - Spóroljunk memóriát!  (Megtekintve 2114 alkalommal)

Nem elérhető krisk

  • 2380
    • Profil megtekintése
String Takarékosság - Spóroljunk memóriát!
« Dátum: 2010. május 01. - 22:57:18 »
+1 Show voters
Stringek
Nos, ahogy Y_Less is leírta az ő SAMPos topicjába, az embereknek elég eltérő nézetük van a stringekkel kapcsolatba. Valaki azt gondolja, nem lehet nagyobb mint 256 cella (ami hülyeség, ugyanis a string limit 1024), valaki azt gondolja, alapból 256 cellát foglal el, és a többi. Nos, megmutatjuk, hogy pazarlás, és meglátjuk, mennyi helyet takaríthatunk meg.
Alapvető tudnivalók
A STRING a pawno-ban karakterek tömbje. Viszont van egy lényeges eltérés. A stringek alapból 1 cella hosszúak. Ugyanis, ha valaki már programozott más nyelveken, tudja, hogy az ASCII minden karakterláncot a \"NULL\" vagy \"\\0\" karakterrel zár le. Lássunk egy jó példát a stringek használatára:
 
new string[3] = \"hi\"

 
Ez három cella hosszú, egy a \"h\" karakternek, egy az \"i\" karakternek, egy pedig a \"NULL\"-nak.
 
new string[3] = { \'h\', \'i\', \'\\0\' }

 
Ez tulajdonképp ugyanaz, csak itt cellánként vannak felosztva a karakterek. A Pawno a stringben minden karaktert a terminátor NULL-ra álílt be, ha meghívjuk, ezért ha ezt írjuk be:
 
new string[256]

 
Tulajdonképp ezt tesszük:
 
for(new i = 0, i < *stringhosszúság*, i++) return str = 0;

 
Rendben, de miért ne használjam?
Mert lassú. Ahogy láthattuk, minnél több stringet adunk meg, annál több lesz a stringhosszúság, így annál több ideig tart a ciklus, echte annál többször kell a karaktereket 0-znia a PAWNO-nak.
Mert nincs rá szükséged. Pl.
 
new modlevel[256]; if(PeepThatShit == 0) new string[256]; format(string,sizeof(string),\"Csak a %d szint feletti adminok tekinthetik meg ezt a valamit.\",ModLevel);

 
Ez egy abszolút rossz példa. Vegyük úgy, egy 5 szintes admin scripttel van dolgunk. Akkor az maximum 1 cellát foglal le, + a NULL. Szóval:
 
new modlevel[2];

 
A stringnek se muszály ekkora értéket adni. Nézzük meg mennyi karakterből áll ez a string:
Ez összesen 61 cellából áll, ugyanis a \"%d\" nem számít bele, szóval -2 karaktert levontunk, ám ezt rögtön a 2 cella hosszú modlevel miatt vissza is kell adni. + a NULL.
 
new modlevel[2]; if(PeepThatShit == 0) new string[61]; format(string,sizeof(string),\"Csak a %d szint feletti adminok tekinthetik meg ezt a valamit.\",ModLevel);

 
Mivel tudjuk, hogy 1 cella 4 bájtból áll, ezért kiszámolhatjuk, hogy össz. 192 cellát mentettünk meg. Ha ezt megszorozzuk néggyel, 768 byte, több mint fél megabájt memóriát vesztettünk.
Chat: Ha a chattel kapcsolatos funkciókat nézzük, akkor a chat imput 128 karakter. Tehát ennyit tudunk összesen a chatbe írni. A 256 cellának a 3/4-ét takarítottuk meg így.
A chat output 256 karakter, tehát ennyit tud maximum a chat kijelezi. Ugyanazt tudom elmondani, mint az előbb, minek 512 cella, ha a fele kárbavész?
Ezenkívül további limiteket is szem előtt tarthatunk ha takarékosságról van szó. Például ha egy adott változóba a játékos nevét tároljuk el, és ha nem vagyunk biztosak a mértékében, jobb, ha az a_samp.inc függvénykönyvtárból hívjuk be a cellahosszot.
 
new IsAnRPName[MAX_PLAYER_NAME]

 
Ugyanez vonatkozik a többi hasonló limitált mennyiségű script property-re.
Másik érdekes példa:
 
public OnPlayerCommandText(playerid, cmdtext[])
{
new
string[256],
cmd[256];
cmd = strtok(cmdtext, idx);
}

 
Ez teljesen hibás.
 

new string[256], cmd[256];
cmd = strtok(cmdtext, idx);

 
Miért kéne a cmd string ide? Mért csinálunk 2 hatalmas változót a parancsnak, és az adatnak is? Az adatot csak akkor használod, ha beírtad a parancsot. Szóval egyszerűsítsük le.
 

new string[256];
string = strtok(cmdtext, idx);

 
Miért 256 cella hosszú? Ahogy előbb már letárgyaltuk, a chatbe max 128 karaktert tudunk beírni. Ezért írjuk is át.
 

new string[128];
string = strtok(cmdtext, idx);

 
Memória (stack): Ha meghívunk egy funkciót, akkor az eltárolódik egy bizonyos stack-ban.
 

new gVar = 2;
stock StackUse()
{
new str[9];
format(str, sizeof (str), \"gVar = %d\", gVar);
SendClientMessageToAll(0xFF0000AA, str);
if (gVar)
{
gVar--;
StackUse();
}
}

 
Nézzük meg mi történik. adunk gVar-nak egy értéket, ami 2, majd csinálunk egy 9 cella értékű stringet (nem pazarlunk) ugyanis a következő érték: \"gVar = \" 7 cellából áll, + a gVar értéke, ami 2. Elküldi a változó értékét, majd lekérdezi, hogy a gVar meghívódott-e. Ha igen, akkor a gVar-t egyesével csökkentjük. Mivel 9 cellával van dolgunk, és a gVar 2, ezt csökkentjük 3 alkalommal (2 > 1 > NULL) mindegyik között a funkció meghívódik mégegyszer.
És mi történik ha 256-tal használunk?
 
new gVar = 2;
stock StackUse()
{
new str[256];
format(str, sizeof (str), \"gVar = %d\", gVar);
SendClientMessageToAll(0xFF0000AA, str);
if (gVar)
{
gVar--;
StackUse();
}
}

 
A gVar-t továbbra is ürítjük, ám a pawno-nak időbe tellik, mire a 256 stringből mindet átírja NULL-ra, ezért a memóriahasználat 2800%-a az eredtinek.
Mikor használjak 256-ot?
MySQL adatbázis lekéréseknél, mivel azoknál nem biztos az adat mennyisége, különösen nem a TEXT típusú adatmezőkben.
Fájlkiolvasás: Szintén nem tudhatjuk, mekkora lesz az output.
Írta Y_Less, kibővítette krisk.
« Utoljára szerkesztve: 2010. május 02. - 08:42:12 írta krisk »

Nem elérhető SnicK

  • 7521
    • Profil megtekintése
String Takarékosság - Spóroljunk memóriát!
« Válasz #1 Dátum: 2010. május 01. - 23:04:42 »
0 Show voters
Kiváló, és igényes munka, most értettem meg igazán hogy értetted ezt x-en.  :angel:

Nem elérhető krisk

  • 2380
    • Profil megtekintése
String Takarékosság - Spóroljunk memóriát!
« Válasz #2 Dátum: 2010. május 02. - 08:42:27 »
0 Show voters
Köszönöm a dicséretet.
Updateltem benne pár dolgot.
« Utoljára szerkesztve: 2010. május 02. - 09:08:49 írta krisk »

 

SimplePortal 2.3.7 © 2008-2024, SimplePortal