2009-03-31 12 views
13

Me gustaría que un conjunto particular de subprocesos de Python tenga el menor impacto posible. Ya estoy usando nice para ayudar a limitar el consumo de CPU. Pero, idealmente, la E/S también sería limitada. (Si es escéptico, por favor, cuénteme y suponga que hay valor en hacer esto, no importa cuánto tarden en correr, puede haber muchos, y hay cosas de mayor prioridad (por lo general) en el misma máquina, etc.)Cómo limitar el consumo de E/S de los procesos de Python (posiblemente usando ionice)?

Una posibilidad parece ser ionice. ¿Hay algún paquete de Python existente para invocar ionice (Google no apareció nada)? No sería difícil escribir código para simplemente ejecutar el comando ionice; pero preferiría evitar escribir código que alguien más ha escrito/probado; a veces hay casos de bordes sutiles, etc. Y, ¿existe una mejor manera de limitar el consumo de E/S?

El man page for ionice sugiere que el valor ionice puede verse afectada por el valor nice, pero la ejecución de este 2.6 script Python parece desmentir que, incluso para los procesos secundarios, donde se hereda el valor 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() 

Que tiene el siguiente resultado:

 
$ 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 

Respuesta

14

psutil expone esta funcionalidad (Python 2.4 -> 3.2):

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

Además, a partir de Python 3.3 estará disponible en stdlib pitón así: http://bugs.python.org/issue10784

+0

Arreglo fresco, desearía que estuviera disponible para OSX. –

+0

sí ... lamentablemente OSX simplemente no lo expone de forma nativa. –

+0

Asegúrate de que tu dispositivo de bloque tenga programador CFQ. De lo contrario, no funcionará. – Zorg

3

por qué no tener lo lanzamientos de los procesos hacen el ionice en ellos (es decir, r uníelos con ionice) en lugar de tenerlos ionice ellos mismos? Parece mucho más limpio.

+0

que efectivamente quiere bifurcar y no ejecutar (por ejemplo, usar el módulo 'multiprocesamiento'); no estoy seguro de dónde encajaría ionice allí. Los niños * podrían * llamar a ionice -p -cblah (en sí mismos, p. Ej., Utilizando os.system). –

5

Hm.

Como puntero de inicio, debe encontrar el número syscall que son las llamadas al sistema ioprio_set y ioprio_get en su kernel. Le sugiero que consulte /usr/include/asm/unistd_32.h o /usr/include/asm/unistd_64.h, dependiendo de su arco del kernel; si no está allí, comience con la sugerencia de la página del manual syscall(2), que debe ser /usr/include/sys/syscall.h y sigue su camino hacia abajo.

Teniendo en cuenta que, se debe utilizar ctypes, al estilo de:

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 

Eso es, más o menos. Divertirse :)

Cuestiones relacionadas