I'm looking for a way to limit a processes disk io to a set speed limit. Ideally the program would work similar to this:
$ limitio --pid 32423 --write-limit 1M
Limiting process 32423 to 1 megabyte per second hard drive writing speed.
That is certainly not trivial task that can't be done in userspace. Fortunately, it is possible to do on Linux, using cgroup
mechanizm and its blkio controller.
Setting up cgroup is somehow distribution specific as it may already be mounted or even used somewhere. Here's general idea, however (assuming you have proper kernel configuration):
mount -t tmpfs cgroup_root /sys/fs/cgroup
mkdir -p /sys/fs/cgroup/blkio
mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
Now that you have blkio
controller set, you can use it:
mkdir -p /sys/fs/cgroup/blkio/limit1M/
echo "X:Y 1048576" > /sys/fs/cgroup/blkio/limit1M/blkio.throttle.write_bps_device
Now you have a cgroup limit1M
that limits write speed on device with major/minor numbers X:Y to 1MB/s. As you can see, this limit is per device. All you have to do now is to put some process inside of that group and it should be limited:
echo $PID > /sys/fs/cgroup/blkio/limit1M/tasks
I don't know if/how this can be done on other operating systems.
echo "X:Y 1073741824" > /sys/fs/cgroup/blkio/blkio.throttle.write_bps_device
and you obtain X and Y by i.e. ls -l /dev/sda
Commented
Apr 20, 2018 at 11:32
dd ... oflag=direct
will work as expected. cgroup v2 can handle this if the filesystem supports it. Details: Using cgroups to limit I/O
ionice
from the util-linux
does something similar to what you want.
It doesn't set absolute IO limits, it sets IO priority and 'niceness' - similar to what nice
does for a process' CPU priority.
From the man page:
ionice - set or get process I/O scheduling class and priority DESCRIPTION This program sets or gets the I/O scheduling class and priority for a program. If no arguments or just -p is given, ionice will query the current I/O scheduling class and priority for that process. When command is given, ionice will run this command with the given arguments. If no class is specified, then command will be executed with the "best-effort" scheduling class. The default priority level is 4.
CFQ
I/O scheduler. Many modern systems have deadline
one enabled by default.
Commented
May 3, 2016 at 8:44
The answer of fche is a very good hint, thanks for that, although it dosn't really solve the problem cause the question was to limit a process to a specific bandwidth.
I would suggest something like this:
systemd-run -p "IOWriteBandwidthMax=/dev/sdX 1M" updatedb
or the deprecated version:
systemd-run -p "BlockIOWriteBandwidth=/dev/sdX 1M" updatedb
Still this does not fit the question cause it cannot be used for an already running process but maybe it's helpfull in some other cases.
Links:
systemd provides a wrapper for cgroup-manipulated invocations of processes. From the systemd-run(1) man page:
The following command invokes the updatedb(8) tool, but lowers the block IO weight for it to 10. See systemd.resource-control(5) for more information on the BlockIOWeight= property.
systemd-run -p BlockIOWeight=10 updatedb
Consider using the --scope
option to make systemd-run
run the program in the foreground.