Supprimer un fichier spécifique du cache du système de fichiers Linux?

23

Je sais que je peux tout supprimer du cache du système de fichiers Linux , mais existe-t-il un moyen de supprimer un seul fichier spécifique? Ou empêcher la mise en cache d'un fichier? Ou dire à un processus de ne pas mettre en cache les fichiers qu'il écrit?

J'ai un processus qui lit beaucoup de petits fichiers et écrit un gros fichier. Je veux garder les petits fichiers en cache pour éviter les recherches de disque, et je ne me soucie pas de mettre en cache le gros fichier.

Jay Hacker
la source
1
En ce qui concerne la prime, je suis spécifiquement intéressé par la question du titre: supprimer un fichier spécifique du cache (par opposition à l'empêcher d'y arriver en premier lieu).
Gilles 'SO- arrête d'être méchant'

Réponses:

21

Méthode potentielle # 1 - F_DROP_CACHES

J'ai trouvé une méthode de 2012 qui discute d'un correctif proposé pour le noyau Linux dans ce fil de discussion intitulé: Re: [RFC Patch] fs: implémente des caches de dépôt par fichier .

extrait

Cong> Ceci est un projet de correctif d'implémentation de caches de dépôt par fichier.

Intéressant. Puis-je le faire en dehors d'un processus? Je suis un administrateur système, donc mon POV consiste à remarquer, à trouver et à résoudre les problèmes de performances lorsque le système est sous pression.

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.

Comment savoir quelle quantité de cache est utilisée par un fichier? Et quel en est l'impact sur les performances lorsqu'il est exécuté sur un système occupé? Et qu'est-ce que ce patch nous achète puisque je pense que la machine virtuelle devrait déjà supprimer des caches une fois que le système est sous pression mem ...

Cong> Ci-dessous est un petit cas de test pour ce patch:

Le thread comprend à la fois un testcase et le correctif réel de plusieurs fichiers dans le noyau Linux qui ajoute une fonction supplémentaire à fs/drop_caches.cappelée drop_pagecache_file(struct file *filp). Cette fonction est ensuite accessible via l'outil frontend, fnctl.cvia la commande F_DROP_CACHES. Ce cas appelle cette fonction:

file_drop_caches(filp, arg);

Qui gère la suppression de tous les caches associés au fichier donné. Du fichier include/linux/mm.h:

void file_drop_caches(struct file *filp, unsigned long which);
Donc, cela peut être utilisé?

Je n'ai trouvé aucune preuve que ce correctif ait jamais fait son chemin dans le référentiel de code du noyau Linux, donc cette option semble être disponible, uniquement si vous êtes prêt à recompiler le noyau Linux vous-même.

Méthode potentielle n ° 2 - Utilisation de dd

Dans ce même fil, un autre utilisateur mentionne une méthodologie complètement différente qui utilise dd.

Ce qui suit est extrait de cet e-mail

Il s'agit d'une fonctionnalité utile. Mais n'est-ce pas déjà fourni POSIX_FADV_DONTNEED? Cette fonctionnalité a été ajoutée à GNU dd (8.11) il y a un an .

Voici les exemples de ce patch:
  • Conseiller de supprimer le cache pour le fichier entier

     $ dd if=ifile iflag=nocache count=0
    
  • Assurer la suppression du cache pour l'ensemble du fichier

     $ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
    
  • Supprimer le cache pour une partie du fichier

     $ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
    
  • Diffusez des données en utilisant uniquement le cache à lecture anticipée

     $ dd if=ifile of=ofile iflag=nocache oflag=nocache
    
Tester

Je ne savais pas à 100% comment tester cela, mais j'ai proposé l'approche suivante.

  1. créer un fichier de 100 Mo

    $ dd if=/dev/urandom of=sample.txt bs=100M count=1
    
  2. suivre les accès aux fichiers à l'aide de fatrace

    $ sudo fatrace | grep sample.txt
    
  3. exécuter topafin que nous puissions surveiller l'utilisation de la mémoire, noter le montant gratuitement.

    $ top
    
  4. ouvrir le fichier, noter la quantité de mémoire libre maintenant. Notez fatracele fichier sample.txt.

    $ cat sample.txt > /dev/null
    
  5. déposez le fichier de la mémoire, notez la quantité de mémoire libre maintenant. Notez la sortie de fatrace.

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

Exemple

Dans le terminal # 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
Dans le terminal # 2:
$ top
...
KiB Mem:   7968336 total,  6900956 used,  1067380 free,   267080 buffers
...
Dans le terminal # 3:
$ sudo fatrace | grep sample.txt
Ouvrez maintenant le fichier, sample.txtet notez la quantité de RAM. Dans le terminal # 1.
$ cat sample.txt > /dev/null
Dans le terminal # 2:
KiB Mem:   7968336 total,  7011896 used,   956440 free,   267336 buffers
Remarquez la sortie de la fatraceborne # 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
Maintenant, supprimez le fichier de la RAM, dans le terminal # 4:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
    oflag=nocache conv=notrunc,fdatasync count=0
Notez la sortie de la fatraceborne # 2:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
Notez la RAM dans le terminal # 3:
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

Il semblerait donc que tout ce qui a été consommé par le fichier en RAM est libéré.

Méthode potentielle # 3 - python-fadvise

Grâce à un commentaire de @frostchutz, il existe un autre outil, un script Python, nommé [pyadvise][4]qui fournit une interface beaucoup plus simple que les ddméthodes ci-dessus . Ce script utilise la même posix_fadvise(2)interface.

Exemple
$ 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

Et si nous répétons le test ci-dessus et utilisons pyadviseà la place de dd:

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

J'ai remarqué une baisse identique de la RAM consommée comme avant lors de l'utilisation dd.

slm
la source
ddtravaille pour moi. Je me suis retrouvé avec chris-lamb.co.uk/projects/python-fadvise moi-même, ce qui est la même chose dans une commande plus évidente.
frostschutz
@frostschutz - très cool. Je n'avais pas entendu parler de cela jusqu'à ce que Gilles demande si quelqu'un savait comment faire cela dans le chat. python-fadviseest beaucoup plus facile, j'ai ajouté un exemple montrant dd.
slm
Le lien pour le script python doit être déplacé dans le corps principal de la question. Les commentaires peuvent disparaître sans laisser de trace. Un montage restera au pire dans l'histoire. Cela dit, une recherche Google le trouve facilement, donc ce n'est pas grave.
Faheem Mitha
Il semble même fonctionner sans sudo, donc toute personne qui peut voir un fichier (même sans autorisation d'écriture) peut voir son cache supprimé, c'est ... intéressant.
frostschutz
1
Il y a os.posix_fadvise()maintenant dans le libray standard de Python.
kawing-chiu
3

En développant la réponse de @ geekosaur, vous pouvez forcer l'utilisation de O_DIRECTen utilisant LD_PRELOAD et le programme ici: http://arighi.blogspot.com/2007/04/how-to-bypass-buffer-cache-in-linux.html

Ce code force O_DIRECTpour tous les fichiers. Cependant, en ajoutant simplement une logique strncmp supplémentaire, __do_wrap_openvous pouvez appliquer sélectivement O_DIRECT.

Avertissement: je n'ai pas testé cela.

Mark Wagner
la source
2

Vous pouvez ouvrir des fichiers individuels avec l' O_DIRECTindicateur (voir man 2 open) - lisez attentivement la section NOTES de cette page de manuel et déterminez si vous le souhaitez / avez également besoin O_SYNC.

geekosaure
la source
1
Eh bien, mon processus est cat, et je préfère ne pas le réécrire. :) J'espérais un outil en ligne de commande ou un /proc/sysbouton.
Jay Hacker
2
Pire que cela, je pense que vous voulez vraiment dire que vous utilisez la redirection, donc votre processus est le shell. Je ne connais pas de moyen par fichier de contrôler cela en dehors du opendrapeau; il faudrait en effet écrire un programme pour le faire. ( cat -udésactive uniquement la stdiomise en mémoire tampon, pas la mise en mémoire tampon du système d'exploitation.)
geekosaur
-2

Si vous souhaitez forcer un fichier à toujours utiliser O_SYNC, vous pouvez le marquer comme tel dans les attributs étendus avec chattr +S $file :

homme chattr:

Lorsqu'un fichier avec le jeu d'attributs «S» est modifié, les modifications sont écrites de manière synchrone sur le disque; cela équivaut à l'option de montage «sync» appliquée à un sous-ensemble des fichiers.

O_SYNC force les données + métadonnées à être écrites dans les tampons de disque, mais il passe toujours par le cache de page. O_DIRECT contourne le cache de pages.

Mais sachez que son ouverture avec O_DIRECT serait préjudiciable aux performances, si le gros fichier auquel il vient d'être ajouté, la différence pourrait être faible. Mais si le gros fichier a été réécrit à des endroits aléatoires, O_DIRECT sera un très gros coup sur les performances, même en tenant compte du fait qu'il l'ayant en cache pourrait éventuellement expulser du cache certains des petits fichiers lus.

Si vous avez le ram pour y conserver tous les petits fichiers, vous pouvez aborder le problème dans l'autre sens. Assurez-vous que les petits fichiers sont toujours dans ram, alors je vous suggère de les copier dans tmpfs :

tmpfs met tout dans les caches internes du noyau et grandit et se réduit pour accueillir les fichiers qu'il contient

Jorge Nerín
la source
chattr +Sn'est pas la même chose que O_DIRECT, c'est la même chose que O_SYNC. O_DIRECTfait en sorte que les lectures ne soient pas mises en cache (c'est le sujet de cette question) et les écritures ne soient pas mises en mémoire tampon, sans aucune garantie. O_SYNCfait que les écritures ne sont pas mises en mémoire tampon.
Gilles 'SO- arrête d'être méchant'
@ Gilles, vous avez raison, j'ai lu la question et j'ai pensé à vider les données sur le disque comme je l'avais fait auparavant. Et il y a une autre différence subtile, mais importante dans ce cas, entre O_DIRECT et O_SYNC, O_DIRECT contourne le cache de page, mais pas O_SYNC, il force les données (et les métadonnées) à être vidées sur le disque, mais il passe par le cache de page et est conservé là pour accélérer les lectures. Dois-je changer O_DIRECT pour O_SYNC dans ma réponse afin de ne pas le laisser avec une affirmation erronée?
Jorge Nerín
Cette question concerne la conservation d'un gros fichier qui a été écrit hors du cache. Je pense que l'ouvrir avec O_DIRECT serait préjudiciable aux performances, et si le gros fichier vient d'être ajouté, la différence pourrait être petite. Mais si le gros fichier a été réécrit à des endroits aléatoires, O_DIRECT sera un très gros coup sur les performances, même en tenant compte du fait qu'il pourrait éventuellement expulser du cache certains des petits fichiers lus.
Jorge Nerín
Changer O_DIRECTpour O_SYNCrendre votre réponse cohérente en interne, mais toujours faux compte tenu de la question.
Gilles 'SO- arrête d'être méchant'