Usunąć określony plik z pamięci podręcznej systemu plików Linux?


23

Wiem, że mogę usunąć wszystko z pamięci podręcznej systemu plików Linux , ale czy istnieje sposób na usunięcie tylko jednego określonego pliku? Lub zapobiec buforowaniu pliku? Lub powiedzieć procesowi, aby nie buforował żadnych zapisywanych plików?

Mam proces, który odczytuje wiele małych plików i zapisuje duży plik. Chcę przechowywać małe pliki w pamięci podręcznej, aby uniknąć przeszukiwania dysku, i nie dbam o buforowanie dużego pliku.


1
Jeśli chodzi o nagrodę, jestem szczególnie zainteresowany tytułem pytania: usunięcie określonego pliku z pamięci podręcznej (w przeciwieństwie do uniemożliwienia mu dotarcia tam w pierwszej kolejności).
Gilles „SO- przestań być zły”

Odpowiedzi:


21

Potencjalna metoda nr 1 - F_DROP_CACHES

Znalazłem metodę z 2012 roku, która omawia proponowaną poprawkę do jądra Linuksa w tym wątku pocztowym zatytułowaną: Re: [Poprawka RFC] fs: zaimplementuj pamięci podręczne dla poszczególnych plików .

fragment

Cong> To jest robocza poprawka implementująca pamięci podręczne dla poszczególnych plików.

Ciekawy. Czy mogę to zrobić spoza procesu? Jestem SysAdminem, więc mój POV polega na zauważaniu, znajdowaniu i naprawianiu problemów z wydajnością, gdy system jest pod presją.

Cong> It introduces a new fcntl command  F_DROP_CACHES to drop  
Cong> file caches of a specific file. The reason is that currently  
Cong> we only have a system-wide drop caches interface, it could  
Cong> cause system-wide performance down if we drop all page caches  
Cong> when we actually want to drop the caches of some huge file.

Skąd mam wiedzieć, ile pamięci podręcznej zajmuje plik? A jaki to ma wpływ na wydajność, gdy jest uruchomiony w obciążonym systemie? Co kupuje nas ta łatka, ponieważ uważam, że VM powinna już zrzucać pamięci podręczne, gdy system znajdzie się pod presją pamięci ...

Cong> Poniżej znajduje się mały przypadek testowy dla tej poprawki:

Wątek zawiera zarówno walizkę testową, jak i aktualną poprawkę do kilku plików w jądrze Linuksa, co dodaje dodatkową funkcję do fs/drop_caches.cwywołanej drop_pagecache_file(struct file *filp). Ta funkcja jest następnie dostępna za pomocą narzędzia interfejsu użytkownika, fnctl.cza pomocą polecenia F_DROP_CACHES. Ten przypadek wywołuje tę funkcję:

file_drop_caches(filp, arg);

Który obsługuje usuwanie wszystkich pamięci podręcznych powiązanych z danym plikiem. Z pliku include/linux/mm.h:

void file_drop_caches(struct file *filp, unsigned long which);
Więc można to wykorzystać?

Nie znalazłem żadnych dowodów na to, że łatka ta kiedykolwiek trafiła do głównego repozytorium kodu jądra systemu Linux, więc ta opcja wydaje się być dostępna, tylko jeśli sam zechcesz ponownie skompilować jądro systemu Linux.

Potencjalna metoda nr 2 - Korzystanie z dd

W tym samym wątku inny użytkownik wspomina o zupełnie innej metodologii, z której korzysta dd.

Oto fragment tego e-maila

Jest to przydatna funkcjonalność. Chociaż nie jest jeszcze wyposażony POSIX_FADV_DONTNEED? Ta funkcjonalność została dodana do GNU dd (8.11) rok temu .

Oto przykłady z tej poprawki:
  • Zaleca się upuszczenie pamięci podręcznej dla całego pliku

     $ dd if=ifile iflag=nocache count=0
    
  • Zapewnij pamięć podręczną dla całego pliku

     $ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
    
  • Upuść pamięć podręczną dla części pliku

     $ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
    
  • Przesyłaj strumieniowo dane, używając tylko pamięci podręcznej z wyprzedzeniem

     $ dd if=ifile of=ofile iflag=nocache oflag=nocache
    
Testuję to

Nie byłem w 100% pozytywny, jak to sprawdzić, ale wpadłem na następujące podejście.

  1. zrób plik 100 MB

    $ dd if=/dev/urandom of=sample.txt bs=100M count=1
    
  2. dostęp do pliku śledzenia za pomocą fatrace

    $ sudo fatrace | grep sample.txt
    
  3. uruchom top, abyśmy mogli monitorować wykorzystanie pamięci, bez dodatkowych informacji.

    $ top
    
  4. otwórz plik, zanotuj teraz ilość wolnej pamięci. Zanotuj fatraceplik sample.txt.

    $ cat sample.txt > /dev/null
    
  5. upuść plik z pamięci, zauważ teraz ilość wolnej pamięci. Zwróć uwagę na wynik fatrace.

    $ sudo dd of=/home/saml/tst/162600/sample.txt \
        oflag=nocache conv=notrunc,fdatasync count=0
    

Przykład

W terminalu 1:
$ dd if=/dev/urandom of=sample.txt bs=100M count=1
1+0 records in
1+0 records out
104857600 bytes (105 MB) copied, 7.37996 s, 14.2 MB/s

$ ls -l sample.txt 
-rw-rw-r--. 1 saml saml 104857600 Oct 17 22:54 sample.txt
W terminalu 2:
$ top
...
KiB Mem:   7968336 total,  6900956 used,  1067380 free,   267080 buffers
...
W terminalu 3:
$ sudo fatrace | grep sample.txt
Teraz otwórz plik sample.txti zanotuj ilość pamięci RAM. W terminalu 1.
$ cat sample.txt > /dev/null
W terminalu 2:
KiB Mem:   7968336 total,  7011896 used,   956440 free,   267336 buffers
Zwróć uwagę na wynik fatracew terminalu 3:
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): RC /home/saml/tst/162600/sample.txt
Teraz usuń plik z pamięci RAM w terminalu 4:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
    oflag=nocache conv=notrunc,fdatasync count=0
Zwróć uwagę na wynik fatracew terminalu 2:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
Zwróć uwagę na pamięć RAM w terminalu 3:
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

Wygląda więc na to, że wszystkie zużyte przez plik w pamięci RAM są zwolnione.

Potencjalna metoda # 3 - python-fadvise

Dzięki komentarzowi @frostchutz istnieje inne narzędzie, skrypt w języku Python, o nazwie, [pyadvise][4]który zapewnia znacznie prostszy interfejs niż powyższe ddmetody. Ten skrypt korzysta z tego samego posix_fadvise(2)interfejsu.

Przykład
$ sudo pyadvise --help
Usage: 
    pyadvise [options] [FILE]..

Options:
  -h, --help        show this help message and exit
  -w, --willneed    The specified files will be accessed in the near future
  -s, --sequential  The application expects to access the specified files
                    sequentially (with lower offsets read before higher ones)
  -d, --dontneed    The specified files will not be accessed in the near
                    future
  -r, --random      The specified files will be accessed in random order
  -o, --noreuse     The specified files will be accessed only once. Under
                    Linux, this operation is a no-op; see contrib/copyfileobj-
                    fadvise.py in the python-fadvise source tree for an
                    example on how to achieve approximately the same effect
  -n, --normal      Indicates that the application has no advice to give about
                    its access pattern for the specified files. If no advice
                    is given for an open file, this is the default assumption
  -v, --verbose     Explain what is being done

A jeśli powtórzymy powyższy test i użyjemy pyadvisezamiast dd:

$ pyadvise -d /home/saml/tst/162600/sample.txt

Zauważyłem identyczny spadek zużycia pamięci RAM, jak poprzednio, kiedy korzystałem dd.


ddpracuje dla mnie. Skończyłem z chris-lamb.co.uk/projects/python-fadvise, co jest tym samym w bardziej oczywistym poleceniu.
frostschutz

@frostschutz - bardzo fajnie. Nie słyszałem o tym, dopóki Gilles nie zapytał, czy ktoś wie, jak to zrobić na czacie. python-fadvisejest o wiele łatwiejsze, dodałem przykład pokazujący dd.
slm

Link do skryptu Pythona powinien zostać przeniesiony do głównej części pytania. Komentarze mogą znikać bez śladu. W najgorszym razie edycja pozostanie w historii. Powiedziawszy to, wyszukiwarka Google znajduje to łatwo, więc nie jest to wielka sprawa.
Faheem Mitha

Wydaje się nawet, że działa bez sudo, więc każdy, kto widzi plik (nawet bez pozwolenia na zapis), może upuścić swoją pamięć podręczną, to ... interesujące.
frostschutz

1
Jest os.posix_fadvise()teraz w standardowym libray Pythona.
kawing-chiu


2

Możesz otwierać pojedyncze pliki z O_DIRECTflagą (patrz man 2 open) - przeczytaj uważnie sekcję UWAGI tej strony podręcznika i zastanów się, czy też chcesz / potrzebujesz O_SYNC.


1
Cóż, mój proces jest cati wolałbym go nie przepisywać. :) Miałem nadzieję na narzędzie wiersza polecenia lub /proc/syspokrętło.
Jay Hacker

2
Co gorsza, podejrzewam, że naprawdę masz na myśli przekierowanie, więc twój proces jest powłoką. Nie znam sposobu kontrolowania tego dla poszczególnych plików poza openflagą; naprawdę musisz napisać program, aby to zrobić. ( cat -uwyłącza tylko stdiobuforowanie, a nie buforowanie systemu operacyjnego).
geekozaur

-2

Jeśli chcesz zmusić plik do używania zawsze O_SYNC, możesz oznaczyć go jako taki w atrybutach rozszerzonych za pomocą chattr +S $file:

człowiek chattr:

Po zmodyfikowaniu pliku z zestawem atrybutów „S” zmiany są zapisywane synchronicznie na dysku; jest to równoważne opcji montowania „synchronizacji” zastosowanej do podzbioru plików.

O_SYNC wymusza zapis danych + metadanych w buforach dyskowych, ale nadal przechodzi przez pamięć podręczną strony. O_DIRECT omija pamięć podręczną strony.

Ale pamiętaj, że otwarcie go za pomocą O_DIRECT byłoby szkodliwe dla wydajności, jeśli duży plik, który jest tylko dołączany, różnica może być niewielka. Ale jeśli duży plik zostanie przepisany w przypadkowych miejscach, O_DIRECT będzie bardzo dużym spadkiem wydajności, nawet biorąc pod uwagę, że posiadanie go w pamięci podręcznej może eksmitować z pamięci podręcznej niektóre małe odczytane pliki.

Jeśli masz ram, aby zatrzymać wszystkie małe pliki, możesz podejść do problemu w drugą stronę. Upewnij się, że małe pliki są zawsze w pamięci RAM, a następnie sugeruję skopiowanie ich do tmpfs :

tmpfs umieszcza wszystko w wewnętrznych pamięci podręcznej jądra oraz rośnie i kurczy się, aby pomieścić pliki w nim zawarte


chattr +Sto nie to samo, co O_DIRECTto O_SYNC. O_DIRECTpowoduje, że odczyty nie są buforowane (o to chodzi w tym pytaniu) i zapisuje, że nie jest buforowane bez żadnej gwarancji. O_SYNCpowoduje, że tylko zapisy nie są buforowane.
Gilles „SO- przestań być zły”

@Gilles masz rację, przeczytałem pytanie i pomyślałem o opróżnieniu danych na dysk tak, jak to zrobiłem wcześniej. I jest jeszcze jedna subtelna, ale ważna w tym przypadku różnica między O_DIRECT i O_SYNC, O_DIRECT omija pamięć podręczną strony, ale O_SYNC nie, wymusza opróżnienie danych (i metadanych) na dysk, ale przechodzi przez pamięć podręczną strony i jest tam przechowywany w celu przyspieszenia odczytów. Czy powinienem zmienić O_DIRECT na O_SYNC w mojej odpowiedzi, aby nie pozostać z niewłaściwą afirmacją?
Jorge Nerín

To pytanie dotyczy przechowywania dużego pliku, który został zapisany poza pamięcią podręczną. Myślę, że otwarcie go za pomocą O_DIRECT byłoby szkodliwe dla wydajności i jeśli duży plik jest tylko dołączany, różnica może być niewielka. Ale jeśli duży plik zostanie przepisany w losowych miejscach, O_DIRECT będzie bardzo dużym spadkiem wydajności, nawet biorąc pod uwagę, że może eksmitować z pamięci podręcznej niektóre małe odczytane pliki.
Jorge Nerín,

Zmiana O_DIRECTna O_SYNCsprawiłaby, że Twoja odpowiedź byłaby wewnętrznie spójna, ale nadal błędna, biorąc pod uwagę pytanie.
Gilles „SO- przestań być zły”
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.