Comment limiter les E / S de processus à une limite maximale?

32

Je cherche un moyen de limiter un disque io de processus à une limite de vitesse définie. Idéalement, le programme fonctionnerait de la même manière:

$ limitio --pid 32423 --write-limit 1M

Processus limitant la vitesse d'écriture du disque dur de 32423 à 1 mégaoctet par seconde.

Sepero
la source

Réponses:

33

Ce n'est certainement pas une tâche banale qui ne peut pas être effectuée dans l'espace utilisateur. Heureusement, il est possible de le faire sous Linux, en utilisant cgroupmechanizm et son contrôleur blkio .

La configuration de cgroup est en quelque sorte spécifique à la distribution car elle peut déjà être montée ou même utilisée quelque part. Voici cependant une idée générale (en supposant que vous ayez la bonne configuration du noyau):

mount -t tmpfs cgroup_root /sys/fs/cgroup
mkdir -p /sys/fs/cgroup/blkio
mount -t cgroup -o blkio none /sys/fs/cgroup/blkio

Maintenant que vous avez blkiodéfini le contrôleur, vous pouvez l'utiliser:

mkdir -p /sys/fs/cgroup/blkio/limit1M/
echo "X:Y  1048576" > /sys/fs/cgroup/blkio/limit1M/blkio.throttle.write_bps_device 

Vous avez maintenant un groupe de contrôle limit1Mqui limite la vitesse d'écriture sur un appareil avec des nombres majeurs / mineurs X: Y à 1 Mo / s. Comme vous pouvez le voir, cette limite est par appareil. Tout ce que vous avez à faire maintenant est de mettre un processus à l'intérieur de ce groupe et il devrait être limité:

echo $PID > /sys/fs/cgroup/blkio/limit1M/tasks

Je ne sais pas si / comment cela peut être fait sur d'autres systèmes d'exploitation.

Krzysztof Adamski
la source
3
Veuillez noter que vous devez d'abord définir la politique totale de l'appareil pour créer des sous-groupes par ie echo "X:Y 1073741824" > /sys/fs/cgroup/blkio/blkio.throttle.write_bps_deviceet vous obtenez X et Y par iels -l /dev/sda
dothebart
cgroup v1 ne prend pas en charge l'écriture différée du cache suivant. Cela signifie que tester une simple commande dd en écrivant dans un fichier standard dans un système de fichiers (plutôt que sur un périphérique) ne montrera probablement aucune limitation. Ne pas utiliser d'écriture différée fonctionnera: dd ... oflag=directfonctionnera comme prévu. cgroup v2 peut gérer cela si le système de fichiers le prend en charge. Détails: Utilisation de cgroups pour limiter les E / S
AB
22

ionicedu util-linuxfait quelque chose de similaire à ce que vous voulez.

Il ne définit pas de limites d'E / S absolues, il définit la priorité et la «gentillesse» des E / S - similaire à ce qui est nicefait pour la priorité CPU d'un processus.

Depuis la page de manuel:

ionice - définir ou obtenir la classe et la priorité de planification des E / S de processus

LA DESCRIPTION
Ce programme définit ou obtient la classe de planification d'E / S et la priorité pour un
programme. Si aucun argument ou juste -p n'est donné, ionice interrogera le
classe d'ordonnancement d'E / S actuelle et priorité pour ce processus.

Quand la commande est donnée, ionice exécutera cette commande avec la donnée
arguments. Si aucune classe n'est spécifiée, la commande sera exécutée
avec la classe de planification "au mieux". Le niveau de priorité par défaut est 4.
cas
la source
5
Il ne faut pas oublier qu'il ne fonctionne qu'avec un CFQplanificateur d'E / S. De nombreux systèmes modernes en ont deadlineun activé par défaut.
Highstaker
8

systemd fournit un wrapper pour les appels de processus manipulés par cgroup. Depuis la page de manuel systemd-run (1):

La commande suivante appelle l'outil updatedb (8), mais réduit le poids d'E / S de bloc pour celui-ci à 10. Voir systemd.resource-control (5) pour plus d'informations sur la propriété BlockIOWeight =.
systemd-run -p BlockIOWeight=10 updatedb

Pensez à utiliser l' --scopeoption pour systemd-runexécuter le programme au premier plan.

fche
la source
7

La réponse de fche est un très bon indice, merci pour cela, même si cela ne résout pas vraiment le problème car la question était de limiter un processus à une bande passante spécifique.

Je suggérerais quelque chose comme ceci:

systemd-run -p "IOWriteBandwidthMax=/dev/sdX 1M" updatedb

ou la version obsolète:

systemd-run -p "BlockIOWriteBandwidth=/dev/sdX 1M" updatedb

Cela ne correspond toujours pas à la question car il ne peut pas être utilisé pour un processus déjà en cours mais peut-être que cela est utile dans certains autres cas.

Liens:

Benibr
la source