Est-ce que le cache de mémoire tampon de disque linux make python cPickle plus efficace que shelve?

StackOverflow https://stackoverflow.com/questions/4060937

Question

est IO plus efficace, en raison du cache de la mémoire tampon de disque linux, lors du stockage de python objets fréquemment consultés sous forme de fichiers séparés cPickle au lieu de stocker tous les objets dans une grande étagère?

ne cache tampon le disque fonctionnent différemment dans ces deux scénarios en ce qui concerne l'efficacité?

Il peut y avoir des milliers de gros fichiers (généralement autour de 100 Mo, mais parfois 1Go), mais beaucoup de RAM (par exemple 64 Go).

Était-ce utile?

La solution

Je ne sais pas d'aucune façon théorique de décider quelle méthode est plus rapide, et même si je l'ai fait, je ne suis pas sûr que je lui faire confiance. Donc, nous allons écrire un code et le tester.

Si nous emballons nos conserves au vinaigre / gestionnaires shelve dans les classes avec une interface commune, il sera facile de les échanger dans et hors de votre code. Donc, si à un moment donné de l'avenir, vous découvrirez l'un est meilleur que l'autre (ou découvrir une façon encore meilleure) tout ce que vous devez faire est d'écrire une classe avec la même interface et vous serez en mesure de brancher la nouvelle classe dans votre code avec très peu de modifications à rien d'autre.

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)

Normalement, vous devriez utiliser PickleManager comme ceci:

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

pendant que vous utiliseriez la ShelveManager comme ceci:

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

Mais les performances du test, vous pouvez faire quelque chose comme ceci:

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())'

Au moins sur ma machine, les résultats sont comme ceci:

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

Il semble donc que ShelveManager peut être plus rapide à la lecture, mais PickleManager peut être plus rapide à l'écriture.

Assurez-vous d'exécuter ces tests vous-même. les résultats de TimeIt peuvent varier en fonction de la version de Python, OS, système de fichiers, le matériel, etc.

En outre, notez mes fonctions write et read génèrent des fichiers très petits. Vous voulez tester cela sur des données similaires à votre cas d'utilisation.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top