W ciągu ostatnich kilku miesięcy miałem bardzo irytujący problem z moim systemem Linux: zacina się przy odtwarzaniu dźwięku Firefoksa, ruchu myszy itp., Z malejącym sub-sekundowym (ale wciąż zauważalnym) zacinaniem co kilka sekund. Problem pogarsza się, gdy pamięć podręczna jest zapełniana lub gdy uruchomione są programy intensywnie wykorzystujące pamięć dyskową / pamięć (np. Oprogramowanie do tworzenia kopii zapasowych) restic
). Jednak gdy pamięć podręczna nie jest pełna (np. Przy bardzo małym obciążeniu), wszystko działa bardzo płynnie.
Patrząc przez perf top
wyjście, widzę to list_lru_count_one
ma wysokie koszty ogólne (~ 20%) w tych okresach opóźnienia. htop
także pokazuje kswapd0
przy użyciu 50-90% procesora (choć wydaje się, że wpływ jest znacznie większy). W czasach ekstremalnego opóźnienia htop
Miernik procesora jest często zdominowany przez użycie procesora jądra.
Jedyne obejście, które znalazłem, to wymuszenie na jądrze zachowania wolnej pamięci ( sysctl -w vm.min_free_kbytes=1024000
) lub do ciągłego upuszczania pamięci podręcznych echo 3 > /proc/sys/vm/drop_caches
. Żadne z nich nie jest oczywiście idealne, ani też nie rozwiązuje go całkowicie; to tylko sprawia, że jest rzadsze.
Czy ktoś ma jakieś pomysły na to, dlaczego tak się dzieje?
Informacja o systemie
- i7-4820k z 20 GB (niedopasowanej) pamięci RAM DDR3
- Reprodukowany na Linuksie 4.14-4.18 na NixOS niestabilny
- Uruchamia kontenery Docker i Kubernetes w tle (co, jak sądzę, nie powinno tworzyć mikrosterowania?)
Co już próbowałem
- Zmiana harmonogramów I / O (bfq) za pomocą wielozakresowych harmonogramów I / O
- Używając
-ck
patchset Con Kolivasa (nie pomógł) - Wyłączanie wymiany, zmiana swapowania, używając zram
EDYTOWAĆ : Dla jasności, oto zdjęcie htop
i perf
podczas takiego opóźnienia. Zwróć uwagę na wysokość list_lru_count_one
Obciążenie procesora i kswapd0
+ wysokie użycie procesora jądra.
źródło
Odpowiedzi:
Wygląda na to, że wypróbowałeś już wiele rzeczy, które zasugerowałbym na początku (poprawianie konfiguracji wymiany, zmiana harmonogramów I / O itp.).
Oprócz tego, co już próbowałeś zmienić, zasugerowałbym zmianę nieco domyślnych ustawień domyślnych dla zachowania zapisu wstecznego maszyny wirtualnej. Jest to zarządzane przez sześć następujących wartości sysctl:
vm.dirty_ratio
: Kontroluje, ile zapisów musi być oczekujących na zapis przed wysłaniem. Obsługuje zapisywanie zwrotne na pierwszym planie (na proces) i jest wyrażone jako całkowity procent pamięci RAM. Domyślnie 10% pamięci RAMvm.dirty_background_ratio
: Kontroluje, ile zapisów musi być oczekujących na zapis przed wysłaniem. Obsługuje zapisywanie zwrotne w tle (w całym systemie) i jest wyrażone jako całkowita liczba RAM. Domyślnie 20% pamięci RAMvm.dirty_bytes
: Taki sam jakvm.dirty_ratio
, z wyjątkiem wyrażonej jako całkowita liczba bajtów. Albo to lubvm.dirty_ratio
zostanie użyty, w zależności od tego, co zostało zapisane jako ostatnie.vm.dirty_background_bytes
: Taki sam jakvm.dirty_background_ratio
, z wyjątkiem wyrażonej jako całkowita liczba bajtów. Albo to lubvm.dirty_background_ratio
zostanie użyty, w zależności od tego, co zostało zapisane jako ostatnie.vm.dirty_expire_centisecs
: Ile setnych części sekundy musi upłynąć, zanim rozpocznie się oczekujący zapis zwrotny, gdy powyższe cztery wartości sysctl nie uruchomiłyby go. Domyślnie 100 (jedna sekunda).vm.dirty_writeback_centisecs
: Jak często (w setnych częściach sekundy) jądro ocenia brudne strony pod kątem zapisu wstecznego. Domyślnie 10 (jedna dziesiąta sekundy).Zatem przy wartościach domyślnych, co dziesiąte sekundy, jądro wykona następujące czynności:
Tak więc powinno być całkiem łatwo zobaczyć, dlaczego wartości domyślne mogą powodować problemy, ponieważ system może próbować zapisać do 4 gigabajty danych do pamięci trwałej co dziesiąty sekundy.
Ogólnym konsensu w tych dniach jest dostosowanie
vm.dirty_ratio
1% pamięci RAM ivm.dirty_background_ratio
2%, co w przypadku systemów z mniej niż 64 GB pamięci RAM powoduje zachowanie równoważne z pierwotnie zamierzonym.Kilka innych rzeczy, na które należy zwrócić uwagę:
vm.vfs_cache_pressure
trochę sysctl. Kontroluje to jak agresywnie jądro odzyskuje pamięć z pamięci podręcznej systemu plików, gdy potrzebuje pamięci RAM. Domyślna wartość to 100, nie obniżaj jej do poniżej 50 (ty będzie uzyskasz naprawdę złe zachowanie, jeśli przejdziesz poniżej 50, w tym warunki OOM), i nie podnosisz tego do znacznie więcej niż około 200 (dużo wyżej, a jądro będzie marnować czas na próby odzyskania pamięci, której naprawdę nie może). Odkryłem, że uderzanie go do 150 w rzeczywistości wyraźnie poprawia szybkość reakcji, jeśli masz dość szybkie przechowywanie.vm.overcommit_memory
sysctl. Domyślnie, jądro użyje heurystycznego podejścia, aby spróbować przewidzieć, ile pamięci RAM może faktycznie przeznaczyć na zatwierdzenie. Ustawienie tego na 1 wyłącza heurystykę i mówi jądru, aby działało tak, jakby miało nieskończoną pamięć. Ustawienie tego na 2 powoduje, że jądro nie zobowiązuje się do zapisywania większej ilości pamięci niż całkowita ilość miejsca wymiany w systemie plus procent rzeczywistej pamięci RAM (kontrolowanej przezvm.overcommit_ratio
).vm.page-cluster
sysctl. Kontroluje to, ile stron jest wymienianych lub wymienianych jednocześnie (jest to logarytmiczna wartość base-2, więc domyślnie 3 tłumaczy na 8 stron). Jeśli faktycznie wymieniasz, może to poprawić wydajność wymiany stron.źródło
transparent_hugepage=never
, ale próbowałem go ponownie włączyć i nie miało to znaczenia.Problem został znaleziony!
Okazuje się, że jest to problem wydajnościowy w odzyskiwaniu pamięci w Linuksie, gdy istnieje duża liczba kontenerów / grup pamięci. (Zastrzeżenie: moje wyjaśnienie może być błędne, nie jestem deweloperem jądra.) Problem został rozwiązany w 4.19-rc1 + w ten zestaw poprawek :
Mój system został szczególnie mocno uderzony, ponieważ uruchomiłem dużą liczbę kontenerów, co prawdopodobnie powodowało pojawienie się problemu.
Moje kroki związane z rozwiązywaniem problemów, na wypadek gdyby były pomocne dla każdego, kto ma podobne problemy:
kswapd0
zużywa tonę procesora, gdy mój komputer się zacinaftrace
(następujący Wspaniały blog wyjaśniający Julii Evan ) aby uzyskać ślad, zobacz tokswapd0
ma tendencję do utknięciashrink_slab
,super_cache_count
, ilist_lru_count_one
.shrink_slab lru slow
, znajdź patchset!źródło