【问题标题】:How to limit I/O consumption of Python processes (possibly using ionice)?如何限制 Python 进程的 I/O 消耗(可能使用 ionice)?
【发布时间】:2009-03-31 18:23:07
【问题描述】:

我希望一组特定的 Python 子流程的影响尽可能低。我已经在使用nice 来帮助限制 CPU 消耗。但理想情况下,I/O 也会受到限制。 (如果持怀疑态度,请取笑我并假设这样做是有价值的;无论他们运行多长时间,都可能有很多,并且(通常)有更高优先级的事情正在进行同一台机器等)

一种可能性似乎是ionice。是否有任何现有的 Python 包用于调用 ionice(谷歌没有发现任何东西)?编写代码来简单地运行ionice 命令并不难;但我宁愿避免编写其他人编写/测试过的代码;有时会出现微妙的边缘情况等。而且,有没有更好的方法来限制 I/O 消耗?

man page for 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()

输出如下:

$ unname -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 **** 很高兴:无 **** *** 家长 *** 不错:0 ionice:无:prio 4 *** 孩子 *** 不错:0 ionice:无:prio 4 **** 很高兴:19 **** *** 家长 *** 不错:19 ionice:无:prio 4 *** 孩子 *** 不错:19 ionice:无:prio 4

【问题讨论】:

    标签: python linux performance unix


    【解决方案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

    【讨论】:

    • 很酷的修复,希望它适用于 OSX。
    • 是的......不幸的是,OSX 并没有在本地公开它。
    • 确保你的块设备有 CFQ 调度器。否则将无法正常工作。
    • 您链接到的问题没有提及ionice(或ioprio_get/ioprio_set)。 Python标准库中仍然缺少该功能,除非由例如实现。 @tzot 的解决方案。只实现了getpriority/setpriority
    【解决方案2】:

    嗯。

    作为起始指针,您应该在内核中找到syscall 编号是ioprio_setioprio_get 系统调用。我建议您签入/usr/include/asm/unistd_32.h/usr/include/asm/unistd_64.h,具体取决于您的内核架构;如果不存在,请从 syscall(2) 手册页的建议开始,它应该是 /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】:

      为什么不让任何启动进程对它们进行 ionice(即,使用 ionice 运行它们)而不是让它们自己进行 ionice?看起来干净多了。

      【讨论】:

      • 我实际上想分叉而不是执行(例如,使用“多处理”模块);不确定 ionice 的位置。孩子可以调用 ionice -p -cblah(在他们自己身上,例如,使用 os.system)。
      • @JacobGabrielson 由于 Linux 内核版本 2.6.13 子进程将继承其父进程的 nice 值并接收默认的 ionice 类 2,这使其具有介于 0 和 7 之间的尽力而为的优先级由(nice + 10 ) // 5 计算。所以你应该能够以这种方式控制它。
      猜你喜欢
      • 2010-10-02
      • 1970-01-01
      • 1970-01-01
      • 2015-01-29
      • 1970-01-01
      • 2011-05-14
      • 1970-01-01
      • 2011-03-25
      • 2015-11-15
      相关资源
      最近更新 更多