Fa buffer cache su disco linux make pitone cPickle più efficiente di accantonare?
Domanda
Python è IO più efficiente, grazie alla cache di buffer del disco Linux, quando si ripone accede di frequente oggetti come file cPickle separati invece di memorizzare tutti gli oggetti in un unico grande scaffale?
Il buffering del disco cache di operare in modo diverso in questi due scenari in relazione al consumo?
Ci possono essere migliaia di file di grandi dimensioni (in genere circa 100Mb, 1Gb ma a volte), ma molto più RAM (ad esempio 64 Gb).
Soluzione
Non so di alcun modo teorico per decidere quale metodo è più veloce, e anche se l'ho fatto, non sono sicuro che mi sarebbe fidare. Quindi cerchiamo di scrivere del codice e testarlo.
Se noi confezioniamo i nostri sottaceto / manager Shelve in classi con un'interfaccia comune, allora sarà facile per scambiarle dentro e fuori del vostro codice. Quindi, se ad un certo punto futuro si scopre uno è migliore dell'altro (o scoprire qualche modo ancora meglio) tutto quello che dovete fare è scrivere una classe con la stessa interfaccia e sarete in grado di collegare la nuova classe nel codice con molto piccole modifiche a qualsiasi altra 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)
In genere, utilizza PickleManager in questo modo:
manager=PickleManager()
manager.load(...)
manager.store(...)
quando devi utilizzare lo ShelveManager in questo modo:
with ShelveManager('/tmp/shelve.dat') as manager:
manager.load(...)
manager.store(...)
Ma per le prestazioni del test, si potrebbe fare qualcosa di simile:
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())'
Almeno sulla mia macchina, il risultato è venuto fuori in questo modo:
read (ms) write (ms)
PickleManager 9.26 7.92
ShelveManager 5.32 30.9
Quindi sembra che ShelveManager può essere più veloce in lettura, ma PickleManager può essere più veloce a scrivere.
Assicurarsi di eseguire questi test da soli. risultati timeit possono variare a causa di versione di Python, sistema operativo, tipo di file system, hardware, ecc
Si noti inoltre le mie funzioni write
e read
generano file molto piccoli. Ti consigliamo di provare questo su dati più simile al vostro caso d'uso.