Pregunta

IO Python es más eficiente, debido a la Linux buffer cache de disco, Al almacenar visitada con frecuencia objetos como archivos separados cPickle En lugar de almacenar todos los objetos en un estante grande?

¿Tiene amortiguar el caché de disco funcionan de diferente manera en estos dos escenarios con respecto a la eficiencia?

Puede haber miles de archivos de gran tamaño (generalmente alrededor de 100 Mb, pero a veces de 1 Gb), pero la cantidad de RAM (por ejemplo, 64 Gb).

¿Fue útil?

Solución

No sé de ninguna manera teórica para decidir qué método es más rápido, e incluso si lo hiciera, no estoy seguro de que iba a confiar en ella. Así que vamos a escribir algo de código y probarlo.

Si nuestro paquete de salmuera / gerentes de estantería en clases con una interfaz común, entonces será fácil para intercambiarlas dentro y fuera de su código. Así que si en algún momento futuro se descubre que uno es mejor que el otro (o descubrir alguna manera aún mejor) todo lo que tiene que hacer es escribir una clase con la misma interfaz y usted será capaz de conectar la nueva clase en el código con muy pocas modificaciones a cualquier otra cosa.

test.py:

import cPickle
import shelve
import os

class PickleManager(object):
    def store(self,name,value):
        with open(name,'w') as f:
            cPickle.dump(value,f)
    def load(self,name):
        with open(name,'r') as f:
            return cPickle.load(f)

class ShelveManager(object):
    def __enter__(self):
        if os.path.exists(self.fname):
            self.shelf=shelve.open(self.fname)
        else:
            self.shelf=shelve.open(self.fname,'n')
        return self
    def __exit__(self,ext_type,exc_value,traceback):
        self.shelf.close()
    def __init__(self,fname):
        self.fname=fname
    def store(self,name,value):
        self.shelf[name]=value        
    def load(self,name):
        return self.shelf[name]

def write(manager):                
    for i in range(100):
        fname='/tmp/{i}.dat'.format(i=i)
        data='The sky is so blue'*100
        manager.store(fname,data)
def read(manager):        
    for i in range(100):
        fname='/tmp/{i}.dat'.format(i=i)        
        manager.load(fname)

Normalmente, se usaría PickleManager como esto:

manager=PickleManager()
manager.load(...)
manager.store(...)

mientras que tendría que utilizar el ShelveManager como esto:

with ShelveManager('/tmp/shelve.dat') as manager:        
    manager.load(...)
    manager.store(...)

Pero al rendimiento de la prueba, se podría hacer algo como esto:

python -mtimeit -s'import test' 'with test.ShelveManager("/tmp/shelve.dat") as s: test.read(s)'
python -mtimeit -s'import test' 'test.read(test.PickleManager())'
python -mtimeit -s'import test' 'with test.ShelveManager("/tmp/shelve.dat") as s: test.write(s)'
python -mtimeit -s'import test' 'test.write(test.PickleManager())'

Por lo menos en mi máquina, los resultados salieron como esto:

                  read (ms)     write (ms)
PickleManager     9.26          7.92 
ShelveManager     5.32          30.9 

Así que parece que ShelveManager puede ser más rápido para leer, pero PickleManager puede ser más rápido en la escritura.

Asegúrese de ejecutar estas pruebas a ti mismo. TimeIt resultados pueden variar debido a la versión de Python, el sistema operativo, el tipo de sistema de archivos, hardware, etc.

Además, tenga en mis funciones write y read generan archivos muy pequeños. Usted querrá poner a prueba esta en datos más similares a su caso de uso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top