Nemám obavy o využití paměti RAM (protože mám dost), ani o ztrátu dat v případě náhodného vypnutí (jelikož moje energie je zálohována, systém je spolehlivý a data nejsou kritická). Ale hodně zpracovávám soubory a mohlo by se mi hodit nějaké zvýšení výkonu.
Proto bych chtěl systém nastavit tak, aby využíval více paměti RAM pro ukládání do mezipaměti pro čtení a zápis systému souborů, agresivně přednačítání souborů (např. předčítání celého souboru, ke kterému přistupuje aplikace v případě, že má soubor rozumnou velikost nebo alespoň načtení napřed velkou část (jinak) a k vyprázdnění vyrovnávací paměti zápisu méně často. Jak toho dosáhnout (je to možné)?
Používám souborové systémy ext3 a ntfs (používám hodně ntfs!) s XUbuntu 11.10 x86.
Přijatá odpověď:
Zlepšení výkonu mezipaměti disku obecně znamená více než pouhé zvětšení velikosti mezipaměti systému souborů, pokud není celý systém se vejde do paměti RAM, v takovém případě byste měli použít jednotku RAM (tmpfs
je dobré, protože umožňuje návrat na disk, pokud v některých případech potřebujete RAM) pro běhové úložiště (a možná skript initrd pro zkopírování systému z úložiště na jednotku RAM při spuštění).
Neřekli jste, zda je vaše úložné zařízení SSD nebo HDD. Zde je to, co mi vyhovuje (v mém případě sda
je pevný disk připojený na /home
a sdb
je SSD připojeno na /
).
Nejprve optimalizujte část načítání věcí z úložiště do mezipaměti:
Zde je moje nastavení pro HDD (pokud máte přepínače, ujistěte se, že je v BIOSu povoleno AHCI+NCQ):
echo cfq > /sys/block/sda/queue/scheduler
echo 10000 > /sys/block/sda/queue/iosched/fifo_expire_async
echo 250 > /sys/block/sda/queue/iosched/fifo_expire_sync
echo 80 > /sys/block/sda/queue/iosched/slice_async
echo 1 > /sys/block/sda/queue/iosched/low_latency
echo 6 > /sys/block/sda/queue/iosched/quantum
echo 5 > /sys/block/sda/queue/iosched/slice_async_rq
echo 3 > /sys/block/sda/queue/iosched/slice_idle
echo 100 > /sys/block/sda/queue/iosched/slice_sync
hdparm -q -M 254 /dev/sda
U pouzdra HDD stojí za zmínku vysoká hodnota fifo_expire_async
(obvykle zápis) a dlouhý slice_sync
aby jeden proces mohl získat vysokou propustnost (nastavte slice_sync
na nižší číslo, pokud narazíte na situace, kdy na některá data z disku paralelně čeká více procesů). slice_idle
je vždy kompromis pro HDD, ale nastavení někde v rozsahu 3-20 by mělo být v pořádku v závislosti na využití disku a firmwaru disku. Raději cílím na nízké hodnoty, ale nastavení příliš nízké zničí vaši propustnost. quantum
Zdá se, že nastavení hodně ovlivňuje propustnost, ale snažte se to udržet na co nejnižší úrovni, abyste udrželi latenci na rozumné úrovni. Nastavení quantum
příliš nízká zničí propustnost. Zdá se, že hodnoty v rozsahu 3-8 fungují dobře s pevnými disky. Nejhorší latence pro čtení je (quantum
* slice_sync
) + (slice_async_rq
* slice_async
) ms, pokud jsem správně pochopil chování jádra. Async se většinou používá při zápisech, a protože jste ochotni zdržet zápis na disk, nastavte obě slice_async_rq
a slice_async
na velmi nízká čísla. Nastavení slice_async_rq
příliš nízká hodnota může zastavit čtení, protože zápis již nemůže být zpožděn po čtení. Moje konfigurace se pokusí zapsat data na disk maximálně po 10 sekundách po předání dat jádru, ale protože můžete tolerovat ztrátu dat při výpadku napájení, nastavte také fifo_expire_async
na 3600000
říci, že 1 hodina je v pořádku pro zpoždění na disku. Stačí zachovat slice_async
nízké, protože jinak můžete získat vysokou latenci čtení.
hdparm
příkaz je vyžadován, aby se zabránilo AAM zabíjet většinu výkonu, který AHCI+NCQ umožňuje. Pokud váš disk vydává příliš mnoho hluku, pak toto přeskočte.
Zde je moje nastavení pro SSD (řada Intel 320):
echo cfq > /sys/block/sdb/queue/scheduler
echo 1 > /sys/block/sdb/queue/iosched/back_seek_penalty
echo 10000 > /sys/block/sdb/queue/iosched/fifo_expire_async
echo 20 > /sys/block/sdb/queue/iosched/fifo_expire_sync
echo 1 > /sys/block/sdb/queue/iosched/low_latency
echo 6 > /sys/block/sdb/queue/iosched/quantum
echo 2 > /sys/block/sdb/queue/iosched/slice_async
echo 10 > /sys/block/sdb/queue/iosched/slice_async_rq
echo 1 > /sys/block/sdb/queue/iosched/slice_idle
echo 20 > /sys/block/sdb/queue/iosched/slice_sync
Zde stojí za zmínku nízké hodnoty pro různá nastavení řezu. Nejdůležitější nastavení pro SSD je slice_idle
který musí být nastaven na 0-1. Nastavením na nulu přesunete všechna rozhodnutí o řazení na nativní NCQ, zatímco nastavením na 1 umožní jádru objednávat požadavky (ale pokud je NCQ aktivní, hardware může řazení jádra částečně přepsat). Otestujte obě hodnoty, abyste zjistili, zda vidíte rozdíl. U řady Intel 320 se zdá, že nastavení slide_idle
na poskytuje nejlepší propustnost, ale nastavením na
1
poskytuje nejlepší (nejnižší) celkovou latenci.
Další informace o těchto laditelných možnostech naleznete na adrese https://www.kernel.org/doc/Documentation/block/cfq-iosched.txt.
Aktualizace v roce 2020 a verze jádra 5.3 (cfq je mrtvá):
modprobe bfq
for d in /sys/block/sd?
do
# HDD (tuned for Seagate SMR drive)
echo bfq > "$d/queue/scheduler"
echo 4 > "$d/queue/nr_requests"
echo 32000 > "$d/queue/iosched/back_seek_max"
echo 3 > "$d/queue/iosched/back_seek_penalty"
echo 80 > "$d/queue/iosched/fifo_expire_sync"
echo 1000 > "$d/queue/iosched/fifo_expire_async"
echo 5300 > "$d/queue/iosched/slice_idle_us"
echo 1 > "$d/queue/iosched/low_latency"
echo 200 > "$d/queue/iosched/timeout_sync"
echo 0 > "$d/queue/iosched/max_budget"
echo 1 > "$d/queue/iosched/strict_guarantees"
# additional tweaks for SSD (tuned for Samsung EVO 850):
if test $(cat "$d/queue/rotational") = "0"
then
echo 36 > "$d/queue/nr_requests"
echo 1 > "$d/queue/iosched/back_seek_penalty"
# slice_idle_us should be ~ 0.7/IOPS in µs
echo 16 > "$d/queue/iosched/slice_idle_us"
echo 10 > "$d/queue/iosched/fifo_expire_sync"
echo 250 > "$d/queue/iosched/fifo_expire_async"
echo 10 > "$d/queue/iosched/timeout_sync"
echo 0 > "$d/queue/iosched/strict_guarantees"
fi
done
Nastavení je velmi podobné, ale nyní používám bfq
místo cfq
protože druhý není dostupný s moderními jádry. Snažím se zachovat nr_requests
co nejnižší, aby bylo možné bfq
pro přesnější kontrolu plánování. Zdá se, že alespoň SSD disky Samsung vyžadují poměrně hlubokou frontu, aby mohly běžet s vysokým IOPS.
Používám Ubuntu 18.04 s balíčkem jádra linux-lowlatency-hwe-18.04-edge
který má bfq
pouze jako modul, takže jej musím načíst, než se na něj budu moci přepnout.
Také dnes používám zram
ale já používám jen 5% RAM na zram. To umožňuje linuxovému jádru používat logiku související s odkládáním, aniž by se dotýkalo disků. Pokud se však rozhodnete pro nulovou výměnu disku, ujistěte se, že z vašich aplikací neuniká RAM nebo nevyhazujete peníze.
Nyní, když jsme nakonfigurovali jádro tak, aby načítalo obsah z disku do mezipaměti s rozumným výkonem, je čas upravit chování mezipaměti:
Podle srovnávacích testů, které jsem provedl, bych se neobtěžoval nastavovat čtení dopředu pomocí blockdev
vůbec. Výchozí nastavení jádra jsou v pořádku.
Nastavte systém tak, aby upřednostňoval výměnu dat souboru před kódem aplikace (nezáleží na tom, zda máte dostatek paměti RAM k uchování celého souborový systém a veškerý kód aplikace a veškerá virtuální paměť alokovaná aplikacemi v RAM). To snižuje latenci pro přepínání mezi různými aplikacemi přes latenci pro přístup k velkým souborům z jediné aplikace:
echo 15 > /proc/sys/vm/swappiness
Pokud dáváte přednost ponechat aplikace téměř vždy v paměti RAM, můžete toto nastavit na 1. Pokud toto nastavíte na nulu, jádro se vůbec nevymění, pokud to nebude nezbytně nutné, aby se zabránilo OOM. Pokud jste byli omezeni pamětí a pracovali jste s velkými soubory (např. střih HD videa), pak by mohlo mít smysl nastavit hodnotu blízkou 100.
V dnešní době (2017) raději nemám swap vůbec, pokud máte dostatek RAM. Bez swapu obvykle ztratíte 200-1000 MB RAM na dlouho běžícím stolním počítači. Jsem ochoten obětovat tolik, abych se vyhnul latenci nejhoršího scénáře (prohození kódu aplikace, když je RAM plná). V praxi to znamená, že preferuji OOM Killer před swapováním. Pokud povolujete/potřebujete swapování, možná budete chtít zvýšit /proc/sys/vm/watermark_scale_factor
také, aby se předešlo určité latenci. Navrhoval bych hodnoty mezi 100 a 500. Toto nastavení můžete považovat za obchodování využití CPU pro nižší latenci swapu. Výchozí hodnota je 10 a maximální možná hodnota je 1000. Vyšší hodnota by měla (podle dokumentace jádra) vést k vyššímu využití CPU pro kswapd
procesy a nižší celkovou latenci swapování.
Dále řekněte jádru, aby upřednostňovalo udržování hierarchie adresářů v paměti před obsahem souborů pro případ, že by bylo potřeba uvolnit část paměti RAM (opět, pokud se vše vejde do paměti RAM, toto nastavení nedělá nic):
echo 10 > /proc/sys/vm/vfs_cache_pressure
Nastavení vfs_cache_pressure
na nízkou hodnotu dává smysl, protože ve většině případů jádro potřebuje znát adresářovou strukturu, než může použít obsah souboru z mezipaměti, a příliš brzké vyprázdnění adresářové mezipaměti způsobí, že souborová mezipaměť bude téměř bezcenná. Zvažte přechod až na 1 s tímto nastavením, pokud máte hodně malých souborů (můj systém má přibližně 150 000 10megapixelových fotografií a počítá se jako systém „spousta malých souborů“). Nikdy jej nenastavujte na nulu nebo adresářová struktura je vždy uchovávána v paměti, i když systému dochází paměť. Nastavení této hodnoty na vysokou hodnotu je rozumné pouze v případě, že máte pouze několik velkých souborů, které se neustále znovu načítají (příkladem může být opět střih HD videa bez dostatečné paměti RAM). Oficiální dokumentace jádra říká, že „zvýšení vfs_cache_pressure výrazně nad 100 může mít negativní dopad na výkon“.
Výjimka: pokud máte opravdu velké množství souborů a adresářů a zřídka se dotýkáte/čtete/vypisujete všechny soubory nastavení vfs_cache_pressure
vyšší než 100 může být moudré. To platí pouze v případě, že nemáte dostatek paměti RAM a nemůžete udržet celou strukturu adresářů v paměti RAM a stále máte dostatek paměti RAM pro běžnou mezipaměť souborů a procesy (např. celopodnikový souborový server se spoustou archivního obsahu). Pokud máte pocit, že potřebujete zvýšit vfs_cache_pressure
nad 100 běžíte bez dostatečné paměti RAM. Zvyšování vfs_cache_pressure
může pomoci, ale jedinou skutečnou opravou je získat více paměti RAM. S vfs_cache_pressure
nastavené na vysoké číslo obětuje průměrný výkon pro celkově stabilnější výkon (to znamená, že se můžete vyhnout opravdu špatnému chování v nejhorším případě, ale musíte se vypořádat s horším celkovým výkonem).
Nakonec řekněte jádru, aby použilo až 99 % paměti RAM jako mezipaměť pro zápisy, a nařiďte jádru, aby využilo až 50 % paměti RAM, než zpomalí proces zápisu (výchozí pro dirty_background_ratio
je 10
). Upozornění:Osobně bych to neudělal, ale tvrdili jste, že máte dostatek paměti RAM a jste ochotni o data přijít.
echo 99 > /proc/sys/vm/dirty_ratio
echo 50 > /proc/sys/vm/dirty_background_ratio
A řekněte, že 1h zpoždění zápisu je v pořádku i pro spuštění zápis věcí na disk (opět bych to neudělal):
echo 360000 > /proc/sys/vm/dirty_expire_centisecs
echo 360000 > /proc/sys/vm/dirty_writeback_centisecs
Další informace o těchto laditelných možnostech naleznete na adrese https://www.kernel.org/doc/Documentation/sysctl/vm.txt
Pokud je všechny vložíte do /etc/rc.local
a na konec zahrňte následující, vše bude v mezipaměti co nejdříve po spuštění (toto udělejte pouze v případě, že se váš souborový systém skutečně vejde do RAM):
(nice find / -type f -and -not -path '/sys/*' -and -not -path '/proc/*' -print0 2>/dev/null | nice ionice -c 3 wc -l --files0-from - > /dev/null)&
Nebo trochu jednodušší alternativa, která by mohla fungovat lépe (mezipaměť pouze /home
a /usr
, proveďte to pouze v případě, že máte /home
a /usr
opravdu se vejde do RAM):
(nice find /home /usr -type f -print0 | nice ionice -c 3 wc -l --files0-from - > /dev/null)&