linux磁盘缓冲区caching是否使python cPickle比shelve更高效?

当IO经常访问的Python对象作为单独的cPickle文件存储,而不是将所有的对象存储在一个大的架子上时,由于linux磁盘缓冲区caching,IO是否更高效?

在这两种情况下,磁盘缓冲区caching在效率方面是否有不同的操作?

可能有成千上万的大文件(通常大约100Mb,但有时是1Gb),但有很多RAM(例如64Gb)。

我不知道有什么理论的方法来决定哪种方法更快,即使我做了,我也不确定我会信任它。 所以我们来编写一些代码并对其进行测试。

如果我们将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,操作系统,文件系统类型,硬件等版本而异。

另外,请注意我的writeread功能生成非常小的文件。 你会想测试这个数据更类似于你的用例。