如何限制Python进程的I/O消耗(可能使用ionice)?

15 投票
3 回答
5197 浏览
提问于 2025-04-15 11:04

我希望一组特定的Python子进程对系统的影响尽可能小。我已经在使用nice来帮助限制CPU的使用。不过,理想情况下,输入输出(I/O)的使用也应该被限制。(如果你对此有疑问,请先假设这样做是有价值的;这些进程运行的时间长短无所谓,可能会有很多这样的进程,而且通常还有更高优先级的任务在同一台机器上运行等等。)

一个可能的解决方案是使用ionice。有没有现成的Python包可以用来调用ionice(谷歌搜索没有找到相关内容)?虽然写代码直接运行ionice命令并不难,但我更希望能避免自己写别人已经写过/测试过的代码;有时候会有一些微妙的边缘情况等等。而且,是否还有更好的方法来限制I/O的使用呢?

ionice的手册页提到ionice的值可能会受到nice值的影响,但运行这个Python 2.6的脚本似乎证明了这一点,即使对于继承了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

3 个回答

3

为什么不让启动这些进程的程序直接给它们设置优先级(也就是用ionice命令来运行它们),而不是让进程自己去设置优先级呢?这样做看起来要简单很多。

5

嗯。

作为一个起点,你应该先找出在你的内核中,ioprio_setioprio_get 这两个系统调用对应的 syscall 编号。我建议你查看 /usr/include/asm/unistd_32.h 或者 /usr/include/asm/unistd_64.h,具体取决于你的内核架构;如果在这两个文件里找不到,可以从 syscall(2) 的手册页开始,手册页的路径应该是 /usr/include/sys/syscall.h,然后逐步查看相关的包含文件。

有了这些信息,你可以使用 ctypes,像这样:

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

就这样,差不多就是这些。祝你玩得开心 :)

18

psutil 这个库提供了这个功能(适用于 Python 2.4 到 3.2 版本):

import psutil, os
p = psutil.Process(os.getpid())
p.ionice(psutil.IOPRIO_CLASS_IDLE)

另外,从 Python 3.3 开始,这个功能也会在 Python 的标准库中提供: http://bugs.python.org/issue10784

撰写回答