web-dev-qa-db-fra.com

Puis-je configurer mon système Linux pour une mise en cache plus agressive du système de fichiers?

Je ne suis pas préoccupé par RAM (car j'en ai assez) ni par la perte de données en cas d'arrêt accidentel (car mon alimentation est sauvegardée, le système est fiable et les données ne sont pas critiques.) Mais je fais beaucoup de traitement de fichiers et je pourrais utiliser une amélioration des performances.

C'est pourquoi j'aimerais configurer le système pour qu'il utilise davantage RAM pour la mise en cache du système de fichiers en lecture et en écriture, pour récupérer de manière agressive les fichiers (par exemple, lire en avance le fichier entier auquel accède une application au cas où le fichier est de taille raisonnable ou au moins en lire une grande partie sinon) et pour vider les tampons d'écriture moins fréquemment. Comment y parvenir (est-ce possible)?

J'utilise des systèmes de fichiers ext3 et ntfs (j'utilise beaucoup ntfs!) Avec XUbuntu 11.10 x86.

124
Ivan

L'amélioration des performances du cache disque est en général plus qu'une simple augmentation de la taille du cache du système de fichiers, sauf si votre système entier est compatible avec RAM auquel cas vous devez utiliser RAM drive (tmpfs is good, car il permet de retomber sur le disque si vous avez besoin du RAM dans certains cas) pour le stockage d'exécution (et peut-être un initrd script pour copier le système du stockage vers RAM lecteur au démarrage).

Vous n'avez pas dit si votre périphérique de stockage est SSD ou HDD. Voici ce que j'ai trouvé qui fonctionne pour moi (dans mon cas, sda est un disque dur monté sur /home et sdb est un SSD monté sur / ).

D'abord, optimisez la partie load-stuff-from-storage-to-cache:

Voici ma configuration pour le disque dur (assurez-vous que AHCI + NCQ est activé dans le BIOS si vous avez des bascules):

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

Il convient de noter que le boîtier du disque dur est élevé fifo_expire_async (généralement en écriture) et long slice_sync pour permettre à un seul processus d'obtenir un débit élevé (définissez slice_sync pour réduire le nombre si vous rencontrez des situations où plusieurs processus attendent des données du disque en parallèle). Le slice_idle est toujours un compromis pour les disques durs, mais le définir quelque part dans la plage 3-20 devrait être correct en fonction de l'utilisation du disque et du firmware du disque. Je préfère viser des valeurs faibles, mais le définir trop bas détruira votre débit. Le paramètre quantum semble affecter beaucoup le débit, mais essayez de le maintenir aussi bas que possible pour maintenir la latence à un niveau raisonnable. Un réglage de quantum trop bas détruira le débit. Les valeurs comprises entre 3 et 8 semblent bien fonctionner avec les disques durs. La latence la plus défavorable pour une lecture est de (quantum * slice_sync) + (slice_async_rq * slice_async) ms si j'ai compris le noyau comportement correctement. L'async est principalement utilisé par les écritures et étant donné que vous êtes prêt à retarder l'écriture sur le disque, définissez à la fois slice_async_rq et slice_async sur des nombres très faibles. Cependant, la définition d'une valeur trop faible pour slice_async_rq peut bloquer les lectures car les écritures ne peuvent plus être retardées après les lectures. Ma configuration essaiera d'écrire des données sur le disque au plus tard 10 secondes après que les données ont été transmises au noyau, mais comme vous pouvez tolérer la perte de données en cas de coupure d'alimentation, définissez également fifo_expire_async sur 3600000 sur dire que 1 heure est acceptable pour le délai sur le disque. Gardez simplement le slice_async bas, car sinon vous pouvez obtenir une latence de lecture élevée.

La commande hdparm est requise pour empêcher AAM de tuer une grande partie des performances autorisées par AHCI + NCQ. Si votre disque fait trop de bruit, sautez cela.

Voici ma configuration pour SSD (Intel 320 series):

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

Ici, il convient de noter les valeurs faibles pour différents paramètres de tranche. Le paramètre le plus important pour un SSD est slice_idle qui doit être défini sur 0-1. Le mettre à zéro déplace toutes les décisions de commande vers NCQ natif tandis que le mettre à 1 permet au noyau de commander les requêtes (mais si la NCQ est active, le matériel peut remplacer partiellement la commande du noyau). Testez les deux valeurs pour voir si vous pouvez voir la différence. Pour la série Intel 320, il semble que définir slide_idle sur 0 donne le meilleur débit, mais le définir sur 1 donne la meilleure latence globale (la plus faible).

Pour plus d'informations sur ces paramètres ajustables, voir https://www.kernel.org/doc/Documentation/block/cfq-iosched.txt .

Maintenant que nous avons configuré le noyau pour charger des éléments du disque vers le cache avec des performances sensibles, il est temps d'ajuster le comportement du cache:

Selon les repères que j'ai faits, je ne prendrais pas la peine de définir la lecture anticipée via blockdev. Les paramètres par défaut du noyau sont corrects.

Réglez le système pour qu'il préfère échanger les données de fichier plutôt que le code d'application (cela n'a pas d'importance si vous en avez assez RAM pour garder entier système de fichiers et tout le code d'application et toute la mémoire virtuelle allouée par les applications en RAM). Cela réduit la latence pour l'échange entre différentes applications sur la latence pour accéder aux gros fichiers à partir d'une seule application:

echo 15 > /proc/sys/vm/swappiness

Si vous préférez garder les applications presque toujours dans RAM vous pouvez le mettre à 1. Si vous le mettez à zéro, le noyau ne sera pas échangé du tout sauf si cela est absolument nécessaire pour éviter le MOO. Si vous étiez en mémoire limité et fonctionnant avec des fichiers volumineux (par exemple, le montage vidéo HD), il peut être judicieux de définir ce niveau à 100.

De nos jours (2017), je préfère ne pas avoir de swap du tout si vous avez assez de RAM. Le fait de ne pas avoir d'échange perdra généralement 200 à 1 000 Mo de RAM sur une machine de bureau de longue durée. Je suis prêt à en sacrifier autant pour éviter la pire latence du scénario (échange de code d'application lorsque RAM is full). En pratique, cela signifie que je préfère OOM Killer au swapping. Si vous autorisez/avez besoin de swapping, vous voudrez peut-être augmenter /proc/sys/vm/watermark_scale_factor, aussi, pour éviter une latence . Je suggérerais des valeurs comprises entre 100 et 500. Vous pouvez considérer ce paramètre comme l'échange de l'utilisation du processeur pour une latence de swap inférieure. La valeur par défaut est 10 et le maximum possible est 1000. Une valeur plus élevée devrait (selon documentation du noya ) résulter dans une utilisation plus élevée du processeur pour les processus kswapd et une latence de permutation globale plus faible.

Ensuite, dites au noyau de préférer garder la hiérarchie des répertoires en mémoire plutôt que le contenu des fichiers au cas où certains RAM doivent être libérés (encore une fois, si tout tient dans la RAM, ce paramètre ne fait rien)):

echo 10 > /proc/sys/vm/vfs_cache_pressure

Définir vfs_cache_pressure sur une valeur faible est logique car dans la plupart des cas, le noyau doit connaître la structure du répertoire avant de pouvoir utiliser le contenu des fichiers du cache et vider le cache du répertoire trop tôt rendra le cache de fichiers presque sans valeur . Pensez à descendre à 1 avec ce paramètre si vous avez beaucoup de petits fichiers (mon système a environ 150K photos de 10 mégapixels et compte comme un système "beaucoup de petits fichiers"). Ne jamais le mettre à zéro ou la structure de répertoires est toujours conservée en mémoire même si le système manque de mémoire. La définition de cette valeur est importante uniquement si vous ne disposez que de quelques gros fichiers qui sont constamment relus (encore une fois, le montage vidéo HD sans assez RAM serait un exemple)). la documentation indique que "l'augmentation de vfs_cache_pressure bien au-delà de 100 peut avoir un impact négatif sur les performances".

Exception: si vous avez une quantité vraiment énorme de fichiers et de répertoires et que vous touchez/lisez/listez rarement tous les fichiers avec un paramètre vfs_cache_pressure supérieur à 100 peut être sage. Cela ne s'applique que si vous n'en avez pas assez RAM et que vous ne pouvez pas conserver toute la structure du répertoire dans RAM et que vous en avez toujours assez RAM pour le cache de fichiers et les processus normaux (par exemple, serveur de fichiers à l'échelle de l'entreprise avec beaucoup de contenu d'archivage). Si vous pensez que vous devez augmenter vfs_cache_pressure au-dessus de 100, vous exécutez sans suffisamment de RAM. Augmenter vfs_cache_pressure peut aider, mais le seul vrai correctif est d'obtenir plus de RAM. Ayant vfs_cache_pressure réglé sur un nombre élevé sacrifie les performances moyennes pour avoir des performances plus stables dans l'ensemble (c'est-à-dire que vous pouvez éviter un comportement très mauvais dans le pire des cas mais avoir pour faire face à de moins bonnes performances globales).

Enfin, dites au noyau d'utiliser jusqu'à 99% du RAM comme cache pour les écritures et demandez au noyau d'utiliser jusqu'à 50% de RAM avant de ralentir le processus en cours d'écriture (par défaut pour dirty_background_ratio est 10). Avertissement: Personnellement, je ne le ferais pas mais vous avez prétendu en avoir assez RAM = et sont prêts à perdre les données.

echo 99 > /proc/sys/vm/dirty_ratio
echo 50 > /proc/sys/vm/dirty_background_ratio

Et dites qu'un délai d'écriture de 1h est suffisant pour même commencer écrire des trucs sur le disque (encore une fois, je ne ferais pas ça):

echo 360000 > /proc/sys/vm/dirty_expire_centisecs
echo 360000 > /proc/sys/vm/dirty_writeback_centisecs

Pour plus d'informations sur ces paramètres ajustables, voir https://www.kernel.org/doc/Documentation/sysctl/vm.txt

Si vous mettez tous ces éléments dans /etc/rc.local et incluez les suivants à la fin, tout sera dans le cache dès que possible après le démarrage (ne faites cela que si votre système de fichiers tient vraiment dans la 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)&

Ou une alternative un peu plus simple qui pourrait mieux fonctionner (cache uniquement /home et /usr, ne le faites que si votre /home et /usr correspond vraiment en RAM):

(Nice find /home /usr -type f -print0 | Nice ionice -c 3 wc -l --files0-from - > /dev/null)&
113
Mikko Rantalainen

Tout d'abord, je ne vous recommande PAS de continuer à utiliser NTFS, car l'implémentation de ntfs sous Linux serait un problème de performances et de sécurité à tout moment.

Vous pouvez faire plusieurs choses:

  • utiliser des fs plus récents tels que ext4 ou btrfs
  • essayez de changer votre planificateur io, par exemple bfq
  • désactiver l'échange
  • utiliser un préchargeur automatique comme preload
  • utiliser quelque chose comme systemd pour précharger lors du démarrage
  • ... et quelque chose de plus

Peut-être que vous voulez essayer :-)

16
Felix Yan

Lisez à l'avance:

Sur les systèmes 32 bits:

blockdev --setra 8388607 /dev/sda

Sur les systèmes 64 bits:

blockdev --setra 4294967295 /dev/sda

Écrivez derrière le cache:

echo 100 > /proc/sys/vm/dirty_ratio

Cela utilisera jusqu'à 100% de votre mémoire libre comme cache d'écriture.

Ou vous pouvez tout faire et utiliser tmpfs. Ceci n'est pertinent que si vous avez RAM assez. Mettez ceci dans /etc/fstab. Remplacez 100G par la quantité de RAM physique.

tmpfs /mnt/tmpfs tmpfs size=100G,rw,nosuid,nodev 0 0

Alors:

mkdir /mnt/tmpfs; mount -a

Utilisez ensuite/mnt/tmpfs.

8
Ole Tange

Vous pouvez définir la taille de lecture anticipée avec blockdev --setra sectors /dev/sda1, où secteurs est la taille souhaitée dans les secteurs de 512 octets.

6
psusi

Mon réglage tueur est très simple et très efficace:

echo "2000" > /proc/sys/vm/vfs_cache_pressure

L'explication de documentation du noya :

vfs_cache_pressure

Contrôle la tendance du noyau à récupérer la mémoire utilisée pour la mise en cache des répertoires et des objets inode.

À la valeur par défaut de vfs_cache_pressure = 100, le noyau tentera de récupérer les dentiers et les inodes à un taux "équitable" par rapport à la récupération de pagecache et de swapcache. La diminution de vfs_cache_pressure fait que le noyau préfère conserver les caches dentry et inode. Lorsque vfs_cache_pressure = 0, le noyau ne récupérera jamais les dentiers et les inodes en raison de la pression de la mémoire, ce qui peut facilement entraîner des conditions de mémoire insuffisante. L'augmentation de vfs_cache_pressure au-delà de 100 fait que le noyau préfère récupérer les dentiers et les inodes.

vfs_cache_pressure à 2000 fait que la majeure partie de l'informatique se produit dans le RAM et écritures de disque très tardives.

2
user55518

Pas lié à la mise en cache d'écriture, mais lié aux écritures:

  • Pour un système ext4, vous pourriez désactiver complètement la journalisation

    Cela réduira le nombre d'écritures sur disque pour une mise à jour particulière, mais peut laisser le système de fichiers dans un état incohérent après un arrêt inattendu, nécessitant un fsck ou pire.

Pour empêcher les lectures de disque de déclencher des écritures sur disque:

  • Montez avec l'option relatime ou noatime

    Lorsque vous lisez un fichier, les métadonnées "dernière heure d'accès" pour ce fichier sont généralement mises à jour. L'option noatime désactivera ce comportement. Cela réduit les écritures de disque inutiles, mais vous n'aurez plus ces métadonnées. Certaines distributions (par exemple Manjaro) l'ont adopté comme valeur par défaut sur toutes les partitions (probablement pour augmenter la durée de vie des SSD de modèles antérieurs).

    relatime met à jour le temps d'accès moins fréquemment, selon des heuristiques qui aident à supporter les applications qui utilisent atime. Il s'agit de la valeur par défaut sur Red Hat Enterprise Linux.

Autres options:

  • Dans les commentaires ci-dessus, Mikko a partagé la possibilité de monter avec l'option nobarrier . Mais Ivailo cité RedHat qui met en garde contre cela. À quel point voulez-vous ces 3% supplémentaires?
1
joeytwiddle