I would like a particular set of Python subprocesses to be as low-impact as possible. I'm already using nice to help limit CPU consumption. But ideally I/O would be limited as well. (If skeptical, please humor me and assume there is value in doing this; it doesn't matter how long they take to run, there can be a lot of them, and there is higher-priority stuff (usually) going on on the same machine, etc.)
One possibility appears to be ionice
. Are there any existing Python packages for invoking ionice
(Google didn't turn up anything)? It wouldn't be difficult to write code to simply run the ionice
command; but I'd prefer to avoid writing code that someone else has written/tested; sometimes there are subtle edge cases, etc. And, is there just a better way to limit I/O consumption?
The man page for ionice suggests that the ionice
value can be affected by the nice
value, but running this Python 2.6 script appears to disprove that, even for child processes where the nice
value is inherited:
#!/usr/bin/env python
import os
import multiprocessing
def print_ionice(name):
print '*** ', name, ' ***'
os.system("echo -n 'nice: '; nice")
os.system("echo -n 'ionice: '; ionice -p%d" % os.getpid())
for niced in (None, 19):
if niced: os.nice(niced)
print '**** niced to: ', niced, ' ****'
print_ionice('parent')
subproc = multiprocessing.Process(target=print_ionice, args=['child'])
subproc.start()
subproc.join()
Which has the following output:
$ uname -as Linux x.fake.org 2.6.27-11-server #1 SMP Thu Jan 29 20:13:12 UTC 2009 x86_64 GNU/Linux $ ./foo.py **** niced to: None **** *** parent *** nice: 0 ionice: none: prio 4 *** child *** nice: 0 ionice: none: prio 4 **** niced to: 19 **** *** parent *** nice: 19 ionice: none: prio 4 *** child *** nice: 19 ionice: none: prio 4
psutil exposes this functionality (python 2.4 -> 3.2):
import psutil, os
p = psutil.Process(os.getpid())
p.ionice(psutil.IOPRIO_CLASS_IDLE)
Also, starting from Python 3.3 this will be available in python stdlib as well: http://bugs.python.org/issue10784
Hm.
As a start pointer, you should find what syscall
number are the ioprio_set
and ioprio_get
system calls in your kernel. I'd suggest you check in /usr/include/asm/unistd_32.h
or /usr/include/asm/unistd_64.h
, depending on your kernel arch; if not there, start with the suggestion of the syscall(2)
man page, which should be /usr/include/sys/syscall.h
and work your way down includes.
Given that, you should use ctypes
, à la:
def ioprio_set(which, who, ioprio):
rc= ctypes.CDLL('libc.so.6').syscall(289, which, who, ioprio)
# some error checking goes here, and possibly exception throwing
That's it, more or less. Have fun :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With