Как ограничить потребление I/O процессов Python (возможно, используя ионизацию)?
Я хотел бы, чтобы определенный набор подпроцессов Python был как можно более низким. Я уже использую nice, чтобы ограничить потребление ЦП. Но в идеале ввод-вывод также будет ограничен. (Если скептически, пожалуйста, юмористируйте меня и предположите, что есть ценность в этом, неважно, сколько времени они будут выполнять, их может быть много, и есть более высокоприоритетные вещи (обычно), происходящие на тот же компьютер и т.д.)
Возможна одна возможность ionice
. Существуют ли какие-либо существующие пакеты Python для вызова ionice
(Google ничего не обнаружил)? Нетрудно написать код, чтобы просто запустить команду ionice
; но я бы предпочел не писать код, который кто-то еще написал/протестировал; иногда есть тонкие случаи кросс и т.д. И есть ли лучший способ ограничить потребление I/O?
справочная страница для ионики предполагает, что значение ionice
может зависеть от значения nice
, но запуск этого Python 2.6 script, как представляется, опровергает это, даже для дочерних процессов, где наследуется значение nice
:
#!/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()
Что имеет следующий вывод:
$ 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
Ответы
Ответ 1
psutil раскрывает эту функциональность (python 2.4 → 3.2):
import psutil, os
p = psutil.Process(os.getpid())
p.ionice(psutil.IOPRIO_CLASS_IDLE)
Кроме того, начиная с Python 3.3, это также будет доступно в python stdlib:
http://bugs.python.org/issue10784
Ответ 2
Hm.
В качестве указателя начала вы должны найти, что syscall
число - это системные вызовы ioprio_set
и ioprio_get
в вашем ядре. Я предлагаю вам проверить /usr/include/asm/unistd_32.h
или /usr/include/asm/unistd_64.h
, в зависимости от вашей арки ядра; если нет, начните с предложения страницы syscall(2)
man, которая должна быть /usr/include/sys/syscall.h
и включает в себя ваш путь вниз.
Учитывая это, вы должны использовать 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
Что это, более или менее. Удачи:)
Ответ 3
Почему бы не запустить какие-либо процессы на ионизацию на них (т.е. запустить их с помощью ионитов), а не самим ионитом? Кажется, все намного чище.