Portál AbcLinuxu, 5. května 2025 22:01
Aktuální verze jádra: 2.6.24-rc6. Citát týdne: David Miller. SLUB v nesnázích. Racionalizace scatter/gather řetězů.
Aktuální předverze je (2. 1. 2008) 2.6.24-rc6, vydaná 20. prosince. Linus: Seznam regresí se zmenšuje, takže zatím to vypadá, že by se mělo podařit vydat jádro 2.6.24 na počátku ledna. Za předpokladu, že se všichni během prázdnin nepřejíme, takže by nikdo nic neudělal. Ale všichni víme, že prázdniny jsou ve skutečnosti doba, kdy si dáme pohov od "opravdové práce", a můžeme tak strávit 24 hodin denně hackováním jádra, že jo? Dlouhý changelog obsahuje všechny podrobnosti.
Aktuální verze -mm stromu je 2.6.24-rc6-mm1. Nedávné změny v -mm (kromě toho, že nefunguje na i386 systémech) zahrnují několik změn v nízkoúrovňovém modelu ovladačů, přepracování tmpfs, aktualizace ext4 a začátek odstraňování atributu fastcall z funkcí.
Starší jádra: 2.4.36 vyšlo 1. ledna s několika opravami.
Pro blázny: 0.01 vydal Abdel Benamrouche také 1. ledna.
Musím říct, že vánoční prázdniny jsou to nejlepší období pro hackování. Většina blbečků je na dovolené, takže ten nepřetržitý proud vyrušování a opravdu hloupých emailů je pryč. Zkrátka můžete pracovat na věcech, na kterých chcete pracovat pořád, ale nikdy na ně nemáte čas.
SLUB alokátor je nová implementace nízkoúrovňového jaderného alokátoru stránek; jde o náhradu dlouho používaného slab alokátoru. SLUB byl začleněn do 2.6.22 a v 2.6.23 byl nastaven jako výchozí alokátor. Do budoucna bylo v plánu, aby SLUB nakonec úplně nahradil slab. Tak to nakonec ještě může dopadnout, ale SLUB se teď potýká s potížemi.
První problém se týká nižšího výkonu v několika specifických situacích. Ukázalo se, že hackbench, který měří výkon plánovače, běží pomaleji, když se používá SLUB. Výkon může být dokonce o polovinu nižší, což je dost na to, aby se to lidem nelíbilo. Tento výsledek byl mnoha lidmi potvrzen; objevily se i zprávy o horším výkonu s proprietárním testem TPC-C, které už tak snadno reprodukovat nešlo. V obou případech to však vypadalo, že vývojáři SLUBu Christophu Lameterovi trvalo opravení chyb až příliš dlouho; koneckonců, reakci na zhoršení výkonu testů je normální poslat hned, když jsou zrovna vánoční prázdniny.
Když se k tomu Christoph dostal, poslal dlouhou analýzu, ve které tvrdí, že rozsah problému je ve skutečnosti docela malý. Uzavřel to slovy: s ohledem na všechna omezení při daném porovnávání si myslím, že nestojí za to se tím zabývat. To nebyla odpověď, v jakou doufal Linus:
Je to fakt úplně jednoduché. Buď řekneš "Jasně, já to opravím", nebo půjde SLUB pryč. Jiná možnost není. Když říkáš "nestojí za to se tím zabývat", tak pro mě je to jasně a zřetelně "tak dejme SLUB pryč".
Tou dobou se objevilo řešení problému v reakci na poznámku, kterou poslal Pekka Enberg. Vyšlo najevo, že podle profilů to vypadá, jako by interní funkce SLUBu nazývaná add_partial() stála za většinou toho spotřebovaného času. SLUB alokátor funguje tak, že rozděluje stránky do objektů stejných velikostí, přičemž v rámci těch stránek nemá žádná svá metadata. Když jsou alokovány všechny objekty ze stránky, SLUB na stránku úplně zapomene. Ale když je jeden z těch objektů uvolněn, musí SLUB danou stránku označit jako "částečnou" a přidat ji do své fronty dostupné paměti. Vypadá to, že k tomuto přidávání částečných stránek docházelo mnohem častěji, než by mělo.
Nástroj hackbench pracuje tak, že rychle posílá data mezi procesory a sleduje, jak plánovač reaguje. V rámci tohoto procesu je vynuceno množství alokačních a uvolňovacích operací, což způsobovalo vytváření spousty částečných stránek. Konkrétní problém byl v tom, že částečná stránka byla po vytvoření přidána na začátek seznamu, takže další alokace alokovala ten jediný objekt, který byl na stránce k dispozici, a z částečné stránky se opět stala plná. A SLUB na ni tedy zapomněl. Když došlo k dalšímu uvolnění, celý cyklus se zopakoval.
Jakmile na tohle Christoph přišel, byla oprava na jeden řádek: částečné stránky by měly být přidávány na konec seznamu, ne na začátek. To dá stránce více času nashromáždit další volné objekty, než z ní zase bude zdroj pro alokace, a minimalizuje se tak přidávání a odstraňování částečných stránek. Výsledky přišly rychle: hackbench regrese byla opravena. Nebyly zveřejněny žádné výsledky testování s TPC-C (licence této sady benchmarků nemá ráda zveřejňování výsledků), ale předpokládá se, že problém byl napraven i tam.
Mezitím se začalo mluvit o jedné poněkud opožděné stížnosti na SLUB: pro SLUB alokátor neexistuje ekvivalent /proc/slabinfo. Soubor slabinfo může být velmi efektivním způsob, jak zjišťovat, co se děje s pamětí, kterou jádro alokuje; rychlé a účinné znázornění aktuální alokační situace. Nástroj slabtop tyto informace zpřístupňuje ještě více. Skutečnost, že při použití SLUBu slabtop nefunguje, některým vývojářům vadí; zdá se pravděpodobné, že až si SLUB najde cestu do distribučních jader, bude si stěžovat ještě více lidí. Uživatelé Linuxu obecně požadují více informací o tom, jak jádro pracuje; odstranění užitečného zdroje informací je nepotěší.
Někteří vývojáři dokonce tvrdili, že soubor slabinfo je součástí uživatelského ABI, a proto musí být zachován navždy. Je však těžké soudit, nakolik může být takové rozhraní opravdu tesáno do kamene; jde o poměrně přímý pohled na vnitřnosti jádra, které se časem mění. Takže argumentace s ABI se asi daleko nedostane, ale potřeba mít možnost dotazovat se na alokační situaci jádra zůstává.
Pracuje se na dvou řešeních tohoto problému. První připravuje Pekka Enberg: patch pro náhradu slabinfo pro SLUB, který poskytuje dostatek informací na to, aby slabtop fungoval. Ale skutečným zdrojem těchto informací bude v budoucnu úctyhodná sada souborů v /sys/slab. Hrabat se v tom adresáři ručně nelze doporučit, zvláště s ohledem na to, že existuje lepší způsob: soubor slabinfo.c, který je součástí zdrojáků jádra (v Documentation/vm). Z něj může být zkompilován nástroj, který poskytuje stručné a užitečné informace o aktuálním použití slabu. Distributoři ten nástroj snad začnou dodávat (měl by se stát součástí sady util-linux); zatím je nutné kompilovat.
Poslední zbývající problém je už skoro tradiční: obávaná zpráva od Al Vira o tom, jak jsou pravidla životnosti souborů v /sys/slab nastavena úplně špatně. Ukázalo se, že i vývojář jako Christoph, který umí hackovat kód pro správu paměti a hezky vyladit systémy o 4096 procesorech, má potíže se sysfs. Stejně jako v podstatě každý, kdo s tím kódem pracuje. Kolují patche, které by sysfs trochu racionalizovaly, což možná odstraní problémy v budoucnu. SLUB ale potřebuje rychlejší opravu. Je-li to však poslední zbývající problém, pak se zdá, že status Jediný Správný Alokátor je skoro na dosah.
API pro řetězení scatterlistů byla patrně nejrušivější novinka v 2.6.24, ačkoliv se jedná o relativně malé množství kódu. Toto API jadernému kódu umožňuje řetězit scatter/gather seznamy pro DMA I/O operace, takže je maximální velikost těchto operací větší. To vede k lepšímu výkonu, zvláště v subsystému blokového I/O. Řetězení scatterlistů je považováno za dobrou věc, ale objevily se stížnosti na stávající implementaci. V současné době musí kód, který by chtěl pracovat se zřetězenými scatterlisty, sestavit řetězy sám - v tom se snadno udělá chyba.
Jeden z přístupů ke zlepšení situace je sg_ring API, které navrhuje Rusty Russell. Tento patch odstraňuje současný přístup ke zřetězování; scatterlisty už nemají žádné položky (které jsou ve skutečnosti kamuflované řetězové ukazatele). Místo toho Rusty zavádí struct sg_ring:
struct sg_ring { struct list_head list; unsigned int num, max; struct scatterlist sg[0]; };
Je zřejmé, že řetězení se přesunulo ze scatterlistů a je z něj teď explicitní linkovaný seznam. Proměnné sledují aktuální a maximální velikosti seznamu, což pomáhá se snížením zátěže na jiných místech. Některé verze patche také přidávají celočíselné pole dma_num, které má obsahovat počet mapovaných scatter/gather položek - ten se může lišit od čísla původně stanoveného ovladačem.
sg_ring s daným počtem scatterlist položek může být deklarována pomocí následujícího makra:
DECLARE_SG_RING(name, max);
Pak by měl být jedním z těchto způsobů inicializován kruh:
void sg_ring_init(struct sg_ring *ring, unsigned int max); void sg_ring_single(struct sg_ring *ring, const void *buf, unsigned int buflen);
Druhá možnost je zkratka pro případy, ve kterých musí být s daným bufferem založen kruh s jedinou položkou.
Sestavení kruhu s více položkami je záležitost alokování tolika samostatných sg_ring položek, kolik je potřeba, a explicitního zřetězení těchto položek pomocí pole list. Pro procházení všech položek kruhu je připraveno pomocné makro, jež skrývá hranice mezi jednotlivými scatterlisty:
struct sg_ring *sg; int i; sg_ring_for_each(ring, sg, i) { /* *sg is the scatterlist entry to operate on */ }
Rusty poslal patche, které převádějí na toto API části SCSI subsystému. Jak poznamenal, převod odstraňuje dost práce spojené se sestavováním a rušením scatterlistů.
Jens Axboe, autor původního kódu pro řetězení scatterlistů, reagoval s tím, že aktuální API bylo psáno tak, aby se minimalizoval dopad na ovladače v 2.6.24. Není to, jak říká, dokončený produkt a situace už se zlepšuje. Pohled na jeho git repozitář ukazuje v API doplňky, které mají podobný cíl jako Rustyho práce.
Jensův přístup ponechává stávající zřetězovací mechanismus, ale balí jej do struktury a několika pomocných funkcí, aby s ním byla snazší práce. Ovladače by pak pracovaly se struct sg_table:
struct sg_table { struct scatterlist *sgl; /* seznam */ unsigned int nents; /* počet mapovaných položek */ unsigned int orig_nents; /* původní velikost seznamu */ };
sg_table se sestaví pomocí:
int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_flags);
Tato funkce nealokuje strukturu sg_table, která musí být předána jako parametr. Místo toho alokuje paměť, která se použije pro pole scatterlist, a zařídí jejich zřetězení. Ovladači, který potřebuje sestavit velkou scatter/gather operaci, teď stačí provést jediné volání sg_alloc_table() a pak běžným způsobem projít seznamem položek scatterlistu. Když je operace dokončena, volání
void sg_free_table(struct sg_table *table);
uvolní alokovanou paměť.
Někdy v době začátku vývoje 2.6.25 bude potřeba rozhodnout o dalším směru API pro řetězení scatterlistů. Možná to nebude ta největší událost, ale stanoví se tím, jak bude v budoucnu psán kód řešící vysoce výkonné I/O. Coby autor začleněného zřetězovacího kódu má Jens asi trochu výhodu, jisté však není nic.
SLUB alokátor je nová implementace nízkoúrovňového jaderného alokátoru stránekSLUB nie je alokator stranok. SLUB je nova implementacia SLAB alokatora, ktory pouziva low-level buddy alokator stranok a priestor na stranke manazuje tak aby umoznil alokaciu s granularitou mensou ako PAGE_SIZE a minimalizoval pritom internu fragmentaciu a (rozumne) efektivne pouzivanie cache.
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.