Április – Lokalizáció hatékonyságának növelése

Zolnai Tamás, 2013. május 3.

   Az előző hónapban elkezdett kódtisztítást folytattam ebben a hónapban is. Több olyan megoldást töröltem, mely a régi rendszer maradványaként volt jelen a kódban. Ezzel egyrészről a kód olvashatóságát és annak egyértelműségét sikerült javítani, másrészről több helyen a feldolgozásból is sikerült törölni néhány felesleges műveletet, így javítva annak hatékonyságán. Ezen felül sikerült egy speciális adatstruktúrát implementálni, melynek köszönhetően a lokalizációs programok hatékonyabban képesek keresni a felhasznált sztringek között.

   Az első változtatásom, ahogy azt már előző beszámolómban is előrevetítettem, a forrásfájlok és a PO fájlok közötti sztringátalakításokkal kapcsolatos. A megoldás alapvető koncepciója, hogy a lokalizációs programokat megvalósító osztályok és a PO osztályok közötti kommunikációban a sztringek normál alakban szerepelnek, semmi olyan átalakítást nem tartalmazva, mely forrásfájlhoz köthető (Pl.: xml átalakítások, escape-elés). Így minden osztálynak csak a hozzá tartozó formátummal kell foglalkoznia és az ahhoz tartozó átalakításokat megvalósítania. Ennek az elkülönítésnek a jótékony hatása leginkább az *.src\*.hrc fájlokat feldolgozó transex3 program esetén figyelhető meg. Eddig a transex3 átalakításai három szinten jelentek meg: közvetlenül a transex3 forráskódjában (export.cxx), a lokalizációs programok által közösen használt kódban (merge.cxx) és a PO osztályok kódjában (po.cxx). Így valóban egy nehezen követhető megoldást sikerült leegyszerűsíteni.

Eredmény:
http://cgit.freedesktop.org/libreoffice/core/commit/?id=d885a85a48a4706934e170b7a6671e5e029089a0

   Ahogy említettem a kódban volt néhány mára már elavult koncepció. Az első ilyen, hogy a lokalizálni kívánt sztringekhez a rendszer eltárolt egy platform attribútumot. Ez egyedül a transex3 programhoz kapcsolódik, mivel az *.src\*.hrc fájlokban volt lehetőség makrók segítségével definiálni platform specifikus sztringeket. Bizonyára azóta más szinten oldották meg a platformok problémáját, mivel a lokalizáció mára már figyelmen kívül hagyja ezeket (a PO fájlok sem tárolják). Egy adatstruktúra azonban még őrizte ennek a megoldásnak az emlékét. A lefordított sztringek forráskódba való beemelése során, a PO fájlokból beolvasott sztringek adatai egy olyan map-ben voltak letárolva, melyben a kulcs ez a platform tulajdonság. Mivel azonban ma már nem használatos ez a tulajdonság ezért, minden esetben egy konstans sztring alapján történt a beszúrás és a keresés (bizonyára egy ideiglenes megoldás). Szóval minden esetben egyetlen adatról volt szó, de annak letárolására egy egész map-et használt a rendszer.

Eredmény:
http://cgit.freedesktop.org/libreoffice/core/commit/?id=be30e0e139ecc068665c8e46020b60356b05cfd6

   A felesleges adatstruktúra mellett ez a platform attribútum a feldolgozásban is felesleges sztringműveleteket jelentett, hiszen az adott makró definícióból ki kellett nyerni a tényleges platform azonosítót. Egy másik hasonló tulajdonság, mely növelte a feldolgozás műveleteit, a szélesség attribútum. Ez a tulajdonság szintén a transex3 programhoz és az általa feldolgozott *.src\*.hrc fájlokhoz köthető. Ezek a fájlok különböző felhasználói felületi elemeket definiálnak fix méretezéssel. Ezen méretek közül a szélesség mértékét valamiért külön felhasználták a lokalizáció során, de ma már ez sem használatos, így a feldolgozásnál külön nem kell foglalkozni vele.

Eredmény:
http://cgit.freedesktop.org/libreoffice/core/commit/?id=9e2d2822063729f450adb734f58106bb64695ce6

   Egy másik régi koncepció volt, hogy a forrásfájlokba, melyekből ma kizárólag az angol stringeket emeljük ki, régen más nyelvű stringek is bekerültek, és az akkor még SDF outputba ezeket is kiemelték a lokalizációs programok. Ahhoz, hogy több nyelvű forrásfájlt ilyen módon fel lehessen dolgozni, le kellett tárolni a különböző nyelvek azonosítóit és azokat felhasználva lehetett eltárolni, illetve kiírni az adott string egyes nyelvi megfelelőit. A több nyelvű koncepció megszűnésével azonban nem szűnt meg a nyelvazonosítókat tároló vektor (ez szintén egyetlen elemet (en-US) tárolt minden esetben) és megmaradtak az ezen vektor bejárását célzó ciklusok is, melyek ciklusmagja minden esetben csak egyszer futott le. Így a kód nem igazán tükrözte a tényleges tevékenységet.

Eredmény:
http://cgit.freedesktop.org/libreoffice/core/commit/?id=4146406205ce6f939944685e1931dcd45f3de708
és
http://cgit.freedesktop.org/libreoffice/core/commit/?id=f167f037351d953e324eb97d6055064efa2d7f59

   Miután sikerült a forráskódból kitakarítani az ily módon megmaradt felesleges kódok nagy részét, áttértem a hatékonyság javításának egy konstruktívabb formájára. Az egyes lokalizálandó sztringek azonosítására négy sztring attribútum szolgál (fájlnév, csoportazonosító, közvetlenazonosító, típus). Mivel ezek közül egyik sem hagyható el, ezért az ezekből összegyúrt sztringazonosító általában elég hosszúvá válik. Éppen ezért az ilyen azonosító alapján való keresés kevéssé hatékony, mint például egy számból álló azonosító esetén. Ezért az adatok közötti keresés hatékonyságának érdekében egy speciálisabb adatstruktúrát hoztam létre, illetve az eddig használt egyszerű hash map-et (unordered_map) módosítottam egy kicsit.

  Az új adatstruktúra hatékonyságának megértéséhez elengedhetetlen megismerni egy kicsit jobban a lokalizáció folyamatát. Két dolgot kell látni. Egyrészről azt, hogy a PO fájlokban a sztringek sorrendje általában megegyezik azok felhasználásának a sorrendjével. Ugyanis ahogy már említettem a lokalizációnak két igen jól elkülöníthető része van: a sztringkiemelés POT fájlokba és a lefordított sztringek beírása a forrásfájlokba. Mindkét lépésben ugyanaz a feldolgozás fut le, és így az érintett sztringek sorrendje mindkét esetben megegyezik. Azonban a PO fájlok frissítésének van egy átfutási ideje és így a folyton változó forráskód ezt a sorrendiséget részben megsérti. Éppen ezért egy olyan adatstruktúrát kellett készíteni, mely ezt a részben teljesülő sorrendiséget használja ki.

   A másik dolog, hogy a PO-kból beolvasott sztringeket legtöbb esetben pontosan egyszer kell felhasználni. Ebből látszik, hogy ideális esetben, mikor a PO fájlok és a forrás fájlok között konzisztencia van, az említett hash map-et valójában a FIFO elv szerint használjuk, annak ellenére hogy ez nem látszik a használatán és a hatékonyságán. Mivel azonban gyakori az inkonzisztencia ezért nem használhatunk egy az egyben egy sor adattípust, hiszen abban nem lehet keresni szükség esetén. Ugyanakkor az eddig használt hash map hatékony keresési lehetőségeket nyújt, legalábbis a sztringkulcsos keresések körében (a probléma a kulcs típusa). Így egyenesen adódott a sor és a hash map egyesítésének ötlete.

   A megoldás lényege, hogy a hash map-en belül definiáltam egy beszúrási sorrendet úgy, hogy az egyes elemek mellé letároltam egy mutatót, mely a beszúrási sorrendben rákövetkező elemre mutat (A hash map-ben az elemek sorrendje teljesen a hash-eléstől függ így arra nem lehet támaszkodni). A lekérdezések során pedig, minden esetben az előzőleg lekérdezett elem rákövetkezőjével kezdjük a keresést. Minél nagyobb a konzisztencia a PO fájlok és a forrásfájlok között, annál kevesebb tényleges keresésre van szükség (ideális esetben 0). Az így módosított hash map interfésze változatlan, csak a működése illeszkedik jobban a FIFO elvre.

   Ez csak egy vázlatos leírása a megoldásnak. További aspektusait nem lenne érdemes itt kifejteni, de azt még érdemes megemlíteni, hogy a LibreOffice által támogatott összes nyelvre való futtatás során, a keresések száma átlagosan úgy egy tizedére illetve egy századára csökken, programtól függően. Ugyanakkor a tesztelés során még az egy századra való csökkenés esetén sem volt látható szignifikáns változás a futási időben. Úgy tűnik a sztringkeresés futási ideje elhanyagolható a feldolgozásé mellett.

Eredmény:
http://cgit.freedesktop.org/libreoffice/core/commit/?id=c7ef2522272579a12eecddded0cbed6d222d3742

Az utolsó hónapban a Base-zel fogok még dolgozni, úgyhogy a lokalizációs modullal való ismeretségem mintegy lezárásaként írtam minden osztályhoz egy rövid leírást az utókor számára.
http://cgit.freedesktop.org/libreoffice/core/commit/?id=29400c568a84339066ef238e836cfeb19f732873

Címkék: , ,

Itt lehet hozzászólni !