tomld #5

Írom át a python kódomat C-be. A felénél túl vagyok.

Úgy gondolom, hogy jó sebességet tudtam már python-ból is kihozni a regex modullal, mivel ott natív kód futott és a legtöbb text manipulációmat ezzel csináltam. Illetve optimalizáltam is sokat. Úgy, hogy sok beépített függvényt használtam, az egyik rendező rutinom 0.6 sec alatt futott, ezt C-ben 0.1 alatt sikerült kihozni.

Mivel C-ben nincs dinamikus string kezelés, ezért az előre nem látott méretekhez egy fix nagy méretet foglalok mindenhol. Ez kicsit szívás lett, mert így /usr/bin/time -v paranccsal azt mutatja, hogy a max rezidens memória foglaltságom 207 MB lett egy alap futtatásnál (sok belső ciklus miatt is elfutott ez a méret). Ez python-nál 40 MB körül van mindig. Most ezt sikerült lefaragnom 5 Mb-ra. Ez már elég jó, viszont a stringek miatt a VM mérete még hatalmas.

Ezt a csökkentést úgy sikerült elérnem, hogy a /proc és /sys virtuális fájlrendszer fájljainak nem foglalok előre nagy mem-et, hanem megnézem a méretüket. Mert ugye ezeknél alapból nincs fájl méret, hanem 0-t ad vissza a rendszer mindig. Ráadásul a Tomoyo-s /sys/kernel/security/tomoyo/ mappán belüli fájloknál még az sincs mint a /proc-ban lévőknél, hogy az ftell megmondja a beolvasott stream után a file pozíciót. Ezért trükköznöm kell úgy, hogy memset-tel zero-ra állítom az egész puffert olvasás előtt, aztán strlen-t futattok rá hogy megkapjam a string méretét. Persze kisebb méretekben pufferelve olvasom az egészet és így lassabb is természetesen, de mivel KB-os méretűek a fájlok és nem is ez a sebesség kritikus rész, ezért ez OK.

Most pedig csinálok magamnak dinamikus string kezelést. Saját malloc és free wrapper-t írtam.

Minden mem foglalásnál a string-eknél 2 plusz long int-el nagyobbat foglalok, és az első 2 adat a lefoglalt mem méretét és a string hosszát fogja mutatni. (64 biten 8 byte per unsigned long ingeter).

|maxlen| |len| |s t r i n g k a r a k t e r e k \0 \0 \0 \0 \0|

Majd a pointert ezek utánra állítom. Így olyan mintha sima mem blokkom lenne, csak -1 és -2 -es pozíciónál van még plusz infóm róla. Ezzel spórolok egy rakás strlen hívást és mindig csak annyi mem-et használok, amennyi kell (4K-s határokkal dolgozok). Ugyanis string másolásnál és összefűzésnél pl. (strncpy és strncat) megnézem hogy elég lesz-e a cél string mérete. Ha nem, akkor foglalok neki új mem-et elegendő mérettel. Ennek méretét mindig duplázom, így log2-es idő alatt elérem a szükséges méretet.

Inkább leimplementálom ezeket magamnak, mert nem akarok a kódhoz a standard C libeken kívül semmi függőséget. Futtatni szeretném Android-tól elkezdve esetleg beágyazott kicsi rendszereken is.

Úgy gondolom hogy a fentiekkel találok egy egészséges egyensúlyt a sebesség és memória használat között.

Hozzászólások

A memória-kezelő wrapperedet nem szeretnéd kiszervezni külön libbe? Máshol is tudnád használni, és pl. engem is érdekelne. :)

-----
"Egy jó kapcsolatban a társunkat az ő dolgában kell támogatni, nem a miénkben."
rand() a lelke mindennek! :)

itt van pastebin-en. semmi optimalizáció nincs benne, erre még nem volt időm, még tesztelnem kell sokat.

kb. ennyi:


char *s = memget2(5);
strcpy2(&s, "egy");
strcat2(&s, "ezmarhosszabb");
printf("%s\n", s);
free2(s);

a második strcat-nél átméretezi a mem-et, mivel az eredetiben nem fér el az eredmény.

itt van egy javított változat a string kezelésemről. lényeg, hogy ha null pointer a cél string, akkor automatikusan lefoglalok neki memóriát. ezt amúgy is megtenném, tehát egy if (!ptr) parancsot kivéve nem jelent lassítást és javítja a kód olvashatóságát is.

ezzel a használat így nézhet ki:


char *s = 0;
strcpy2(&s, "egy string");
strcat2(&s, " es hozza fuzve");
printf("%s\n", s);
strnull2(&s);
strcat2(&s, "ez uj string");
free2(s);

most hogy mar megirtad a string kezelest, mind1. de legkozelebb nezd meg, hatha valaki ezt mar megirta jol. (pl lighty-ek)

--
A vegtelen ciklus is vegeter egyszer, csak kelloen eros hardver kell hozza!

a "dinamikus" string kezelésem előtt a VM mérete tomld futása közben 30 és 50 MB között volt mindig, most a memóra spórolós kódommal pedig 4-5 MB hasonló bemenettel.