4

すべてのオブジェクトを 1 つの大きなシェルフに格納するのではなく、頻繁にアクセスされる Python オブジェクトを個別の cPickle ファイルとして格納する場合、Linux ディスク バッファ キャッシュにより、IO はより効率的ですか?

効率に関して、これら 2 つのシナリオでディスク バッファー キャッシュの動作は異なりますか?

何千もの大きなファイル (通常は約 100Mb、場合によっては 1Gb) が存在する可能性がありますが、大量の RAM (64 Gb など) があります。

4

1 に答える 1

3

どちらの方法がより高速であるかを決定する理論的な方法を私は知りません。それでは、コードを書いてテストしてみましょう。

pickle/shelve マネージャーを共通のインターフェイスを持つクラスにパッケージ化すると、それらをコード内外で簡単に交換できます。したがって、将来のある時点で一方が他方よりも優れていることを発見した場合 (またはさらに優れた方法を発見した場合)、同じインターフェースを持つクラスを作成するだけで、新しいクラスを次のようにコードにプラグインできます。他のものへの変更はほとんどありません。

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)

通常、PickleManager は次のように使用します。

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

次のように ShelveManager を使用します。

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

ただし、パフォーマンスをテストするには、次のようにします。

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

少なくとも私のマシンでは、結果は次のようになりました。

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

したがって、読み取りは ShelveManager の方が速いようですが、書き込みは PickleManager の方が速いようです。

これらのテストは必ず自分で実行してください。Timeit の結果は、Python のバージョン、OS、ファイルシステムの種類、ハードウェアなどによって異なる場合があります。

writeまた、 myおよびread関数は非常に小さなファイルを生成することに注意してください。ユースケースにより近いデータでこれをテストする必要があります。

于 2010-10-31T00:13:29.327 に答える