( asch | 2024. 03. 29., p – 14:32 )

Van ilyenre konkrét példád?

Ugye ha elérünk egy bonyolultsági szintet, akkor hirtelen nagyon sok munka ASM-ben befejezni a programot, és ha közben optimalizálni is kell, akkor pláne végtelen szívássá válhat. Vannak például ilyen "legygorsabb ez-az" versenyek, a generátor template-ekkel és web szerverekkel foglalkoztam egy kicsit. Mindkettő esetén az van, hogy a top megoldások kihasználják a lehetőségek maximumát, és ott akadnak el.

Idén volt a "1 billion row challenge", érdemes megnézni milyen trükköket használtak a legjobb megoldások: ASM-ben írva is lényegében csak a JVM indítás overheadjén tudnánk faragni, ami nem sok lévén hogy binárisra fordítós JVM-et használtak a legjobbak. A nem-Java megoldások sem tudtak sokkal gyorsabbak lenni úgy tudom, bár rendes összehasonlító táblázatot nem találtam.

A template engineket például Java nyelvre néztem - bevallom megpróbáltam gyorsabbat csinálni mint a leggyorsabb itt és utolérni sikerült, de legyorsulni nem: https://github.com/agentgt/template-benchmark - , és a benchmarknak a legjobbak esetén az lett a bottleneckje, hogy Java stringet kell visszaadni és a bájtfolyamból Java string objektum készítés meglehetősen időigényes, lassú folyamat. Amint ez lesz a bottleneck, ott nincs mit tenni, nem lehet tovább javítani a teljesítményt a platform fejlesztése nélkül. Mivel a string kezelés körülményes és lassú Javában, ezért template nyelvből szerintem sokkal gyorsabbat lehet csinálni C-ben. Kivéve, ha Javában is úgy döntünk, hogy mostantól a string az csak egy MemorySegment. Újra kell írni az összes String formázó API-t, de a végén a C-vel/ASM-mel pariban lehetünk teljesítményben. És ha csak a szűk keresztmetszetet optimalizáljuk így ki, akkor összességében még mindig kevesebbet dolgoztunk mintha teljesen C-ben vagy akár ASM-ben indultunk volna el.

A web szerverek esetén jóval a RAM sávszélesség előtt a kernelhívások overheadje lett a szűk keresztmetszet. Lényegében a kiszolgáláshoz szükséges kernelhívásokat mérte a benchmark a legjobb versenyzők esetén. Mivel ez lett a szűk keresztmetszet, ezért ASM-ben írva sem tudtam volna jelentősen jobb eredményt elérni mint a legjobb Java megvalósítás - és a pályamű évek munkája lett volna nyilván ASM-ben.

Két fajta válasz is lett erre a problémára. Az egyik az io_uring API, ami arra ad lehetőséget, hogy sokkal kevesebb kernel kontextusváltással tudunk átadni IO parancsokat a kernelnek. Aki ezt először be tudta építeni a megoldásába az hirtelen hülyére verte a többit.

A másik válasz az volt, hogy tegyük be a http szervert a kernelbe! Amennyire unortodoxnak hangzik, én néha tényleg nem értem, hogy ha egy szerver 1 dolgot csinál, akkor miért is kell a kernelt védeni a userspace-től? Hiszen minden ami fontos úgyis a userspace-ben van, nem? Tegyünk inkább mindent a Kernelbe, kapcsoljuk ki a kernel védelmeit a fenébe, és lássunk csodát micsoda teljesítményeket lehet elérni így!

De ezek már más méretskálán vannak mint locsemege mikrovezérlős dolgai.