Jak korzystać z przestrzeni wymiany tylko w sytuacjach awaryjnych?

41

Mam laptopa Debian (Buster) z 8 GB pamięci RAM i 16 GB wymiany. Prowadzę bardzo długie zadanie. Oznacza to, że mój laptop był włączony przez ostatnie sześć dni, gdy się przepełniał.

Robiąc to, okresowo muszę używać laptopa jako laptopa. To nie powinno stanowić problemu; długo działające zadanie jest związane z operacjami we / wy, pracując na dyskach twardych USB i nie zajmuje dużo pamięci RAM (<200 MB) ani procesora (<4%).

Problem polega na tym , że gdy wrócę do laptopa po kilku godzinach, będzie bardzo powolny i powrót do normy może zająć 30 minut. Jest to tak złe, że monitory awarii sygnalizują, że ich odpowiednie aplikacje zostały zawieszone (zwłaszcza okna przeglądarki) i wszystko zaczyna się niepoprawnie zawieszać.

Patrząc na monitor systemowy, z 2,5 GB używanej około połowy zmienia się w swap. Potwierdziłem, że to jest problem, usuwając przestrzeń wymiany ( swapoff /dev/sda8). Jeśli zostawiam go bez przestrzeni wymiany, wraca do życia prawie natychmiast, nawet po 24 godzinach. Dzięki zamianie jest to właściwie cegła przez pierwsze pięć minut, która pozostała tylko na sześć godzin. Potwierdziłem, że użycie pamięci nigdy nie przekracza 3 GB, nawet gdy mnie nie ma.

Próbowałem sprowadzić swapiness ( patrz także: Wikipedia ) do wartości 10i 0, ale problem nadal występuje. Wygląda na to, że po dniu bezczynności jądro uważa, że ​​cały GUI nie jest już potrzebny i czyści go z pamięci RAM (zamienia na dysk). Długotrwałym zadaniem jest czytanie przez rozległe drzewo plików i czytanie każdego pliku. Więc może być tak, że jądro jest zdezorientowane myśleniem, że buforowanie pomoże. Ale przy jednym przejściu 2 TB USB HD z ~ 1 miliardem nazw plików, dodatkowa pamięć RAM RAM nie poprawi wydajności. To tani laptop z powolnym dyskiem twardym. Po prostu nie może wystarczająco szybko załadować danych z powrotem do pamięci RAM.

Jak mogę powiedzieć Linuksowi, aby korzystał z przestrzeni wymiany tylko w sytuacjach awaryjnych? Nie chcę biegać bez zamiany. Jeśli wydarzy się coś nieoczekiwanego, a system operacyjny nagle potrzebuje dodatkowych kilku GB, nie chcę, aby zadania zostały zabite i wolałbym zacząć korzystać z wymiany. Ale w tej chwili, jeśli pozostawię włączoną zamianę, mojego laptopa po prostu nie można używać, gdy jest to potrzebne.

Dokładna definicja „sytuacji nadzwyczajnej” może być przedmiotem dyskusji. Ale aby wyjaśnić, co mam na myśli: w nagłym przypadku system miałby miejsce bez żadnej innej opcji niż zamiana lub zabijanie procesów.


Co to jest nagły wypadek? - Czy naprawdę musisz zapytać? ... Mam nadzieję, że nigdy nie znajdziesz się w płonącym budynku!

W tym pytaniu nie mogę zdefiniować wszystkiego, co mogłoby stanowić sytuację wyjątkową. Ale na przykład może się zdarzyć sytuacja, gdy jądro jest tak wypychane do pamięci, że zaczęło zabijać procesy za pomocą OOM Killera . Awaryjne NIE jest, gdy jądro uważa, że ​​może poprawić wydajność za pomocą swap.


Ostateczna edycja: Zaakceptowałem odpowiedź, która robi dokładnie to, o co prosiłem na poziomie systemu operacyjnego. Przyszli czytelnicy powinni również wziąć pod uwagę odpowiedzi oferujące rozwiązania na poziomie aplikacji.

Philip Couling
źródło
11
Zdefiniuj „awaryjne” i powiedz coś o tym, jak różni się to od zwykłej sytuacji, w której zostanie użyta wymiana.
Kusalananda
4
Chciałem wiedzieć, czy chcesz w jakiś sposób zdefiniować specjalny rodzaj „zdarzenia awaryjnego” poza limitem, który pozwoliłby jądru na korzystanie z zamiany, ale w przeciwnym razie ta zamiana nie byłaby używana. AFAIK stronicowanie pamięci to coś, co jest powolne i zawsze robione „w nagłych wypadkach”, a „zamiana” jest jedyną rzeczą, za pomocą której możesz dostosować to zachowanie (ale nie jestem użytkownikiem Linuksa).
Kusalananda
2
Nie, to nie jest poprawne. Odbywa się to nie tylko w sytuacjach awaryjnych. Przynajmniej myślałem, że moje pytanie wyjaśniło, że użyłem tylko 3 GB z 8 GB ... To nie jest sytuacja nadzwyczajna, ale jądro i tak się zmienia. Sugeruję poczytać o swapiness i otaczających go tematach. Istnieje wiele dyskusji na temat różnych powodów zamiany. Możliwe, że pytam o koncepcję, która nie istnieje w jądrze, ale moje powody, dla których o nią prosiłem, są dość dobrze uzasadnione.
Philip Couling,
4
Rozumiem, że rada zawsze brzmiała: „nigdy nie biegaj bez zamiany”. Ale rozmiary pamięci mają wyskalowane prędkości odczytu / zapisu dysku twardego (HDD nie SSD), co oznacza, że ​​zamiana staje się coraz bardziej złym pomysłem. Wydaje się, że niektórzy uważają, że 8 GB pamięci RAM + 8 GB wymiany spowoduje wykonanie 16 GB pamięci RAM + 0 wymiany. Jeśli naprawdę tak jest, to coś jest nie tak z jądrem Linuksa.
Philip Couling
7
@Filip Couling: Nie, chodzi o to, że 16 GB pamięci RAM + 16 GB wymiany przewyższy 16 GB i 0 wymiany - szczególnie gdy twój kod potrzebuje 17 GB pamięci :-)
jamesqf

Odpowiedzi:

11

Posiadanie tak dużej wymiany w dzisiejszych czasach jest często złym pomysłem. Zanim system zamienił zaledwie kilka GB pamięci do wymiany, Twój system już zaindeksował na śmierć (tak jak to widziałeś)

Lepiej jest używać zramz małą partycją wymiany kopii zapasowych . Wiele systemów operacyjnych, takich jak ChromeOS, Android i różne dystrybucje Linuksa, domyślnie włącza zram od lat, szczególnie w systemach z mniejszą pamięcią RAM. Jest to znacznie szybsze niż zamiana na HDD i w tym przypadku możesz wyraźnie poczuć reakcję systemu. Mniej na SSD, ale zgodnie z wynikami testu porównawczego tutaj wydaje się jeszcze szybszy, nawet przy domyślnym algorytmie Lzo. Możesz zmienić na lz4, aby uzyskać jeszcze lepszą wydajność przy nieco mniejszym stopniu kompresji. Jego prędkość dekodowania jest prawie 5 razy większa niż Lzo w oparciu o oficjalny test porównawczy

Jest też, zswapchociaż nigdy go nie użyłem. Prawdopodobnie warto spróbować i porównać, który jest lepszy dla twoich przypadków użycia

Następnie kolejną sugestią jest zmniejszenie priorytetu tych procesów związanych z IO i ewentualnie pozostawienie terminalu o wyższym priorytecie, aby można było od razu uruchomić na nim polecenia, nawet gdy system jest obciążony

Dalsza lektura

phuclv
źródło
Właśnie dla zrozumienia, że ​​mówisz, że mogę utworzyć zramurządzenie blokowe, użyć go jako wymiany, z wymianą o niższym priorytecie jako partycji dysku twardego?
Philip Couling
@ PhilipCouling, jeśli używasz HDD, to tak, zdecydowanie powinieneś użyć zram lub podobnych rozwiązań. Priorytet wymiany powinien być niższy niż zram, więc Linux najpierw spróbuje użyć zram, a następnie rozważy zamianę. Jeśli używasz Ubuntu, pakiet zram-config już dba o ustawienia priorytetów dla Ciebie
phuclv
3
Przyjmuję tę odpowiedź, ponieważ wydaje się, że robi dokładnie to, o co prosiłem. Jeśli nadal mam włączoną zamianę 16 GB ze zmniejszonym priorytetem, jądro będzie jej używać dopiero po wyczerpaniu zswap. IE: „w nagłym wypadku”. Uwaga na temat debian-buster jest bardzo łatwa w instalacji, po prostu instalując narzędzia zram.
Philip Couling
25

Jedną z poprawek jest upewnienie się, że kontroler grupy pamięci jest włączony (myślę, że jest domyślnie w nawet najnowszych jądrach, w przeciwnym razie będziesz musiał dodać cgroup_enable=memoryje do wiersza poleceń jądra). Następnie możesz uruchomić intensywne zadanie we / wy w grupie c z limitem pamięci, który również ogranicza ilość pamięci podręcznej, którą może zużyć.

Jeśli używasz systemd, możesz ustawić +MemoryAccounting=yesi MemoryHigh/ MemoryMaxlub MemoryLimit(zależy od tego, czy używasz cgroup v1 lub v2) w urządzeniu, czy też plaster zawierający go. Jeśli jest to plasterek, możesz użyć go systemd-rundo uruchomienia programu w plasterku.

Pełny przykład jednego z moich systemów do uruchamiania Firefoksa z limitem pamięci. Zauważ, że używa cgroups v2 i jest skonfigurowane jako mój użytkownik, a nie root (jedna z zalet v2 nad v1 polega na tym, że delegowanie tego do użytkownika innego niż root jest bezpieczne, więc systemd robi to).

$ systemctl --user cat mozilla.slice 
# /home/anthony/.config/systemd/user/mozilla.slice
[Unit]
Description=Slice for Mozilla apps
Before=slices.target

[Slice]
MemoryAccounting=yes
MemoryHigh=5G
MemoryMax=6G

$ systemd-run --user --slice mozilla.slice --scope -- /usr/bin/firefox &
$ systemd-run --user --slice mozilla.slice --scope -- /usr/bin/thunderbird &

Stwierdziłem, że aby uruchomić użytkownika, musiałem użyć plastra. System pierwszy działa po prostu poprzez umieszczenie opcji w pliku usługi (lub użycie systemctl set-propertyw usłudze).

Oto przykładowa usługa (przy użyciu cgroup v1), zwróć uwagę na dwie ostatnie linie. Jest to część wystąpienia systemu (pid = 1).

[Unit]
Description=mount S3QL filesystem
Requires=network-online.target
After=network-online.target

[Install]
WantedBy=multi-user.target

[Service]
Type=forking
User=s3ql-user
Group=s3ql-user
LimitNOFILE=20000
ExecStartPre=+/bin/sh -c 'printf "S3QL_CACHE_SIZE=%%i\n" $(stat -c "%%a*%%S*.90/1024" -f /srv/s3ql-cache/ | bc) > /run/local-s3ql-env'
ExecStartPre=/usr/bin/fsck.s3ql  --cachedir /srv/s3ql-cache/fs1 --authfile /etc/s3ql-authinfo  --log none «REDACTED»
EnvironmentFile=-/run/local-s3ql-env
ExecStart=/usr/bin/mount.s3ql --keep-cache --cachedir /srv/s3ql-cache/fs1 --authfile /etc/s3ql-authinfo --cachesize ${S3QL_CACHE_SIZE} --threads 4
ExecStop=/usr/bin/umount.s3ql /mnt/S3QL/
TimeoutStopSec=2m
MemoryAccounting=yes
MemoryLimit=1G

Dokumentacja jest w systemd.resource-control(5).

derobert
źródło
1
Czy nie możesz zrobić czegoś porównywalnego i przenośnego, używając tylko ulimit?
Old Pro
1
@OldPro nie bardzo. Po pierwsze, nie ma AFAIK limitu całkowitego zużycia pamięci, w tym pamięci podręcznej strony (która jest tutaj nadmiernym zużyciem). Po drugie, ulimit dla pamięci jest procesem, cgroups działają nawet, jeśli rozwiąże się długo działające zadanie.
derobert
Myślałem, że powodem, dla którego rozliczanie pamięci jest domyślnie włączone w nowszych systemach, jest zmiana w systemdwersji 238 .
sourcejedi
1
@sourcejedi, który jest stosunkowo nowy. Kiedy kontroler pamięci został wprowadzony po raz pierwszy, samo udostępnienie (nawet nieużywanie) miało wystarczająco duży koszt wydajności, że niektórzy dystrybutorzy przynajmniej domyślnie go wyłączali i trzeba było przekazać ten argument wiersza poleceń jądra, aby go włączyć. Problemy z wydajnością zostały naprawione, więc uległy zmianie, a ostatnio systemd również je aktywuje domyślnie.
derobert
14

Wygląda na to, że po dniu bezczynności jądro uważa, że ​​cały GUI nie jest już potrzebny i czyści go z pamięci RAM (zamienia na dysk).

Jądro robi The Right Thing ™, wierząc w to. Dlaczego miałby utrzymywać nieużywaną 1 pamięć w pamięci RAM i tak właściwie marnować ją zamiast używać jej jako pamięci podręcznej lub czegoś takiego?

Nie sądzę, aby jądro Linuksa wymieniało strony bezinteresownie lub z wyprzedzeniem, więc jeśli tak się dzieje, musi to być przechowywanie czegoś innego w pamięci RAM, co poprawia wydajność twojego długotrwałego zadania, a przynajmniej z tym celem.

Jeśli wiesz, kiedy będziesz musiał ponownie użyć laptopa, możesz użyć atpolecenia (lub crontab), aby zaplanować czyszczenie wymiany ( swapoff -a;swapon -a).

Ponieważ czyszczenie wymiany może być nadmierne, a nawet wywołać zabójcę OOM, jeśli z jakiegoś powodu nie wszystko mieści się w pamięci RAM, możesz po prostu „cofnąć wymianę” 2 wszystkiego, co związane z uruchomionymi aplikacjami, które chcesz przywrócić.

Jednym ze sposobów na to byłoby dołączenie debuggera takiego jak gdbkażdy z procesów, których dotyczy problem, i uruchomienie generowania zrzutu podstawowego:

# gdb -p <pid>
...
generate-core-dump /dev/null
...
quit

Jak napisałeś, twoja długo działająca aplikacja nie wykorzystuje ponownie danych, które odczytuje po wstępnym przejściu, więc jesteś w szczególnym przypadku, w którym długoterminowe buforowanie nie jest przydatne. Następnie obejście pamięci podręcznej przy użyciu bezpośrednich operacji we / wy, jak sugeruje Will Crawford, powinno być dobrym rozwiązaniem.

Alternatywnie, możesz po prostu regularnie opróżnić pamięć podręczną plików przez echo 1lub 3do /proc/sys/vm/drop_cachespseudo-pliku przed OS uważa, że to dobry pomysł, aby zamienić swoje aplikacje GUI i środowiska.

Zobacz Jak opróżniasz bufory i pamięć podręczną w systemie Linux? dla szczegółów.

1 Nieużywany w tym sensie: nie jest już aktywnie wykorzystywany od dłuższego czasu, pamięć jest nadal ważna dla jego właścicieli.
2 Włóż z powrotem do stron pamięci RAM zapisanych w obszarze wymiany.

jlliagre
źródło
2
Dzięki za przemyślenie możliwych przyczyn. Dodałem trochę do pytania, ponieważ może być istotne. Zastanawiam się, czy istnieje sposób na obniżenie priorytetu buforowania względem własnej pamięci aplikacji.
Philip Couling
5
„Nie sądzę, aby jądro Linuksa wymieniało strony bezinteresownie lub z wyprzedzeniem, więc jeśli to zrobi, musi to być przechowywanie czegoś innego w pamięci RAM, co poprawi wydajność”. - Myślę, że to sformułowanie jest nieco dwuznaczne. Jądro z pewnością napisze strony do zamiany, ilekroć ma taką możliwość (np. Jest mało dyskowych operacji we / wy). Nie usunie ich jednak z pamięci RAM. W ten sposób masz to, co najlepsze z obu światów: jeśli ponownie szybko potrzebujesz tych stron, są one już w pamięci RAM i nie ma nic do zrobienia. Jeśli wystąpi nagły wypadek (jak to ujęła OP), po prostu potrzebujesz wolnych stron w pamięci RAM, ponieważ
Jörg W Mittag
3
… Są już w wymianie. I właśnie dlatego nie chcesz używać swap „tylko w nagłych wypadkach”, ponieważ w sytuacji awaryjnej system jest już obciążony, a ostatnią rzeczą, jakiej chcesz, jest dodanie do niego dużych ilości We / Wy dysku.
Jörg W Mittag
2
Problemem powodującym zamianę jest prawdopodobnie długotrwały proces: dostęp do plików na dysku. Te pliki w pamięci będą ostatnio używane niż pamięć GUI.
jpmc26
3
@ JörgWMittag Czy masz dowody na to, że jądro Linuksa jest niskie, gdy użycie We / Wy jest niskie, zapobiegawczo zapisujesz strony w obszarze wymiany „na wszelki wypadek”, tzn. Bez uwalniania ich z pamięci RAM?
jlliagre
10

Czy proces, który uruchamiasz, sam stworzyłeś?

Jeśli tak, warto poprawić kod, aby otworzyć pliki za pomocą O_DIRECTflagi, która zacytowała stronę podręcznika -

Spróbuj zminimalizować efekty bufora we / wy do iz tego pliku. Zasadniczo obniży to wydajność, ale jest to przydatne w szczególnych sytuacjach, na przykład gdy aplikacje wykonują własne buforowanie. Pliki we / wy są wykonywane bezpośrednio do / z buforów przestrzeni użytkownika. Flaga O_DIRECT sama podejmuje próbę synchronicznego przesyłania danych, ale nie daje gwarancji flagi O_SYNC, że dane i niezbędne metadane są przesyłane. Aby zagwarantować synchroniczne operacje we / wy, oprócz O_DIRECT należy użyć O_SYNC. Patrz UWAGI poniżej, aby uzyskać dalszą dyskusję.

Will Crawford
źródło
1
Innym podobnym (ale prawdopodobnie łatwiejszym, ponieważ jestem całkiem pewien, że O_DIRECT ma ograniczenia wyrównania i zabijesz wydajność, jeśli twoje odczyty nie są duże) jest fadvise, aby poinformować jądro, że nie będziesz potrzebować tych danych ponownie, usuwając je z pamięć podręczna strony. (telefonicznie lub
podałby
1
@derobert Po pierwsze, nocachepolecenie to wygodny hack, aby to zrobić. (Używa LD_PRELOAD do przejęcia niektórych wywołań libc).
sourcejedi
6

Oto pomysł, którego sam nie próbowałem (i przepraszam, że nie mam teraz czasu na eksperymentowanie z tym).

Załóżmy, że tworzysz małą maszynę wirtualną z tylko 512 MB pamięci na potrzeby procesu w tle. Nie jestem pewien, czy chcesz, aby miała ona zamianę, połączenie i wyłączenie wymiany w systemie hosta.

X Tian
źródło
3

Usuń swap lub zmniejsz go o około 20% ( może różnić się w zależności od systemu ), ponieważ ostatnio systemy operacyjne nie używają swapu w taki sam sposób, jak kilka lat temu. Prawdopodobnie odpowiada na niektóre z twoich pytań:

-> oficjalny redhat.com

niektóre z informacji Red Hat poniżej,

W przeszłości niektórzy dostawcy aplikacji zalecali zamianę rozmiaru równego pamięci RAM, a nawet dwukrotności pamięci RAM. Teraz wyobraźmy sobie wyżej wymieniony system z 2 GB pamięci RAM i 2 GB wymiany. Baza danych w systemie została przez pomyłkę skonfigurowana dla systemu z 5 GB pamięci RAM. Po zużyciu pamięci fizycznej następuje zamiana. Ponieważ dysk wymiany jest znacznie wolniejszy niż pamięć RAM, wydajność spada i pojawia się wstrząsanie. W tym momencie nawet logowanie do systemu może stać się niemożliwe. W miarę jak zapisuje się coraz więcej pamięci, w końcu zarówno pamięć fizyczna, jak i pamięć wymiany są całkowicie wyczerpane, a zabójca OOM uruchamia się, zabijając jeden lub więcej procesów. W naszym przypadku dostępnych jest sporo swapów, więc czas słabej wydajności jest długi.

i

https://wiki.debian.org/Swap

część linku Debiana powyżej,

Informacje i rozważania związane z ilością swapów do wykorzystania:

„Zalecana ilość miejsca wymiany tradycyjnie była dwukrotnie większa niż pamięć systemowa. Zmieniło się to z czasem do półtora raza pamięci systemowej, obie odpowiedzi są przyzwoitymi wartościami podstawowymi, ale z czasem stają się coraz mniej użytecznymi odpowiedziami na pytanie. Istnieje wiele zmiennych dotyczących twojego systemu i zamierzonego zastosowania, które określą dostępną zamianę systemu, którą będziesz chciał mieć. ”

Możesz spróbować:

„Najlepszy sposób na wyłączenie wymiany w systemie Linux”


Notatka osobista:


Ponieważ mam 6 GB pamięci RAM i cały mój ostatnio system operacyjny Linux. Nigdy nie widziałem żadnych oznak używania Swap. Ustaliłem, że muszę go wyłączyć albo dla przestrzeni (kilka gigabajtów więcej), a ponieważ czasami spowalnia mój system.

Tyþë-Ø
źródło
1
W przeszłości niektórzy dostawcy aplikacji zalecali zamianę rozmiaru równego pamięci RAM, a nawet dwukrotności pamięci RAM. Czuję się o wiele starszy, widząc to w jakiś sposób ... Mimo że nadal mam jeden z dysków twardych przy barierze ~ 528 MB, a także 2,5 GB, jakoś ten cytat - cóż, to jest coś z bardzo dawno ... Jednak ciekawy cytat i może to wyjaśniać, dlaczego kilka lat temu widziałem podobne problemy. Wydaje mi się, że użyłem sysctl, aby to naprawić, ale nie pamiętam dokładnie, jakie ustawienie, gdyby to była wigilia.
Pryftan