Egyszerű optimalizációval a Linux 7.4 akár 39%-kal gyorsabban nyitja meg a fájlokat olvasásra

enlightened Ez az oldal a közösségért készül. heart Kövess minket máshol is:  Linux Mint Magyar Közösség a Mastodon-on  Telegram csatorna – csak hírek  Beszélgessünk a Telegram – Linux csevegő csoport  Hírek olvasása RSS segítségével  Linux Mint Hivatalos Magyar Közösség a Facebook-on      Linux Mint Baráti Kör a Facebook-on
wink Ha hasznosnak találod, és szeretnéd, hogy folytatódjon, támogasd a munkát Ko-fi vagy Paypal segítségével. laugh

kami911 képe

A nyílt forráskódú szoftvereken dolgozó fejlesztő, Mateusz Guzik vezeti azt a munkát, amely a Linux kernel do_open() VFS függvényének optimalizálására irányul. Ezt a függvényt a fájlmegnyitás során használják, amikor az elérési útból kikeresik a fájlt. Jelenleg a folyamat során duplikált könyvtárbejegyzés, úgynevezett „dentry” jön létre, amely a path komponensből a lemezen lévő inode-ra fordít. Guzik ezt a felesleges dentry-t iktatja ki. Guzik a javítócsomagban magyarázta el a részleteket, amely az elmúlt két évben öt változáson ment át:

"A fájl megnyitásakor a __legitimize_path() fog egy hivatkozást a végső dentry-re, majd a do_dentry_open() fog még egyet, végül a terminate_walk() eldobja az első hivatkozást.

Ez 2 fölösleges módosítás – a do_dentry_open() felhasználhatja a már meglévő hivatkozást is."

Az ilyen felesleges munka elhagyása meglepően nagy előnyt hoz: egy 20 magos virtuális gépen, a will-it-scale benchmarkkal mérve, ahol ugyanazt a fájlt nyitják meg csak olvasásra, a másodpercenkénti műveletek száma 39%-kal nőtt. Meglepő, hogy egy ilyen „könnyen lecsíphető” optimalizáció ilyen sokáig bent maradt a Linux kernel-ben. Jó hír viszont, hogy a fejlesztés várhatóan 2026 vége előtt bekerül a stabil kernel-be. A nagyjából három tucat sornyi kódból álló javítócsomagot már beütemezték a VFS.Git vfs-7.4.lookup Git ágba. Mivel a javítócsomag mostanra egy hivatalos VFS alrendszerbeli Git ágban van, és „7.4-es” anyagként jelölték meg, várhatóan benyújtják az érkező Linux 7.4 merge ablakában.

A VFS, a dentry, az inode és a fájl megnyitása

A Linux kernel fájlkezelésének egyik legfontosabb eleme a VFS (Virtual File System, virtuális fájlrendszer), amely egységes felületet biztosít a különböző fájlrendszerek, például az ext4, az XFS vagy a Btrfs és az alkalmazások között. Amikor egy program egy fájl megnyitását, lekérdezését vagy módosítását kéri, a VFS feladata, hogy a megadott útvonalból megtalálja a hozzá tartozó fájlrendszer-objektumot.

Ebben fontos szerepet játszik a dentry cache, röviden dcache. A dentry, vagyis directory entry egy kernelbeli objektum, amely elsősorban egy fájlnév vagy könyvtárnév és a hozzá tartozó fájlrendszer-objektum közötti kapcsolatot képviseli. Ha például egy program a /home/felhasznalo/dokumentum.txt fájlt akarja megnyitni, a VFS az útvonal egyes elemein végighaladva keresi meg a megfelelő dentryket. A már korábban használt útvonalakhoz tartozó dentryk a memóriában található dcache-ben maradhatnak, így a kernelnek nem kell minden alkalommal újra végrehajtania a teljes keresést. Ez jelentősen felgyorsítja a fájlnevek feloldását.

A dentry cache azonban csak gyorsítótár, nem maga a fájlrendszer. A dentryk alapvetően a teljesítmény javítása érdekében léteznek a memóriában, és a kernel szükség esetén újra létre tudja őket. Ha egy keresett dentry nincs a cache-ben, a VFS a konkrét fájlrendszer segítségével megkeresi a hozzá tartozó objektumot.

Itt kerül képbe az inode. Az inode a fájlrendszer egy objektumát – például egy normál fájlt, könyvtárat vagy más fájlrendszer-objektumot – reprezentálja, és annak fontos metaadatait tartalmazza. Ide tartozhat például a fájl mérete, típusa, jogosultsága, tulajdonosa és időbélyegei. Fontos különbség, hogy az inode nem a fájl nevét tárolja. A fájlnév feloldásában a dentry vesz részt, amely az inode-ra hivatkozik. Emiatt akár több különböző dentry is ugyanarra az inode-ra mutathat, például hard linkek esetén.

Miután a VFS megtalálta a megfelelő dentryt és inode-ot, a fájl még nincs feltétlenül megnyitva. Az open() rendszerhívás során a kernel létrehoz egy file objektumot, amely az adott megnyitás kernelbeli reprezentációja. Ez kapcsolja össze a megnyitott fájlhoz tartozó állapotot a dentryvel és az inode által meghatározott fájlrendszer-műveletekkel. A felhasználói program ebből végül egy file descriptort, vagyis fájlleírót kap, például a 3 értéket. Amikor a program később read(), write() vagy close() műveletet hajt végre, ezt a fájlleírót használja a kernel a megfelelő file objektum megtalálásához.

A folyamat tehát leegyszerűsítve úgy képzelhető el, hogy a program egy útvonalat ad meg, a VFS ebből megkeresi a megfelelő dentryt, a dentry segítségével eljut az inode-hoz, majd a fájl megnyitásakor létrejön a hozzá tartozó file objektum, amelyhez a program egy file descriptoron keresztül fér hozzá. A dentry tehát elsősorban a név feloldásában, az inode a fájlrendszer-objektum leírásában, a file objektum pedig az adott megnyitás kezelésében fontos.

Ennek a folyamatnak van egy kevésbé látványos, de teljesítmény szempontjából fontos része is: a hivatkozásszámlálás (reference counting). A kernelnek nyilván kell tartania, hogy egy adott objektumot – például egy dentryt – hány kernelbeli felhasználó tart még életben. Amíg van rá érvényes hivatkozás, az objektumot nem lehet egyszerűen felszabadítani. Ez egy általános és alapvető memória- és objektumélettartam-kezelési mechanizmus a Linux kernelben.

A fájl megnyitásának folyamatában a dentry hivatkozásszámlálása is változhat. A megadott kódrészlet szerint a fájl megnyitásakor a __legitimize_path() egy hivatkozást szerez a végső dentryre, majd a do_dentry_open() további hivatkozást szerez ugyanarra a dentryre. Ezután a terminate_walk() eldobja az első hivatkozást.

Ez önmagában működőképes, de azt jelenti, hogy ugyanannak az objektumnak a hivatkozásszámlálóját feleslegesen kétszer módosítják: egyszer növelik, majd később csökkentik, miközben a második hivatkozás továbbra is szükséges. A megfogalmazás szerint ezért két fölösleges hivatkozásszámláló-módosítás történik. A javasolt optimalizáció lényege, hogy a do_dentry_open() egyszerűen felhasználhatná a __legitimize_path() által már megszerzett hivatkozást, ahelyett, hogy újabbat venne.

Ez első látásra apró változtatásnak tűnik, hiszen nem a fájl tartalma, nem a fájlrendszer struktúrája és nem is a felhasználó által érzékelhető működés változik meg. A kernelben azonban az ilyen műveletek nagyon gyakran, nagyon sokszor hajtódnak végre. Egy fájl megnyitásakor néhány extra referencia-számláló-művelet önmagában gyakorlatilag mérhetetlen lehet, nagyon sok fájlművelet során összeadódva viszont felesleges CPU-munkát és memória-koherencia-forgalmat jelenthet.

A hivatkozásszámlálás különösen érdekes többmagos rendszereken, mert az ilyen számlálók módosítása nem egyszerűen egy változó átírását jelenti. A kernelnek biztosítania kell, hogy párhuzamosan futó processzorok és kernel-szálak mellett is helyes maradjon az objektum élettartama. Emiatt a referencia megszerzése és elengedése megfelelő szinkronizációt és memóriaműveleteket igényelhet. Ha tehát egy hivatkozás már rendelkezésre áll, annak felesleges eldobása és egy újabb megszerzése kerülendő.

A változtatás jelentősége ezért nem abban áll, hogy látványosan megváltozik a fájlok megnyitásának működése, hanem abban, hogy a kernel egy gyakran végrehajtott útvonalán csökkenti a szükségtelen munkát. Ez tipikusan olyan kerneloptimalizáció, amely önmagában apróságnak tűnik, de a fájlmegnyitások nagy száma miatt összességében javíthatja a hatékonyságot.