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).

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top