当将频繁访问的python对象作为单独的cPickle文件存储而不是将所有对象存储在一个大型书架中时,由于linux磁盘缓冲区缓存,IO是否更有效?linux磁盘缓冲区缓存是否使python cPickle比shelve更高效?
在这两种情况下,磁盘缓冲区缓存在效率方面是否运行不同?
可能有成千上万的大文件(通常大约100Mb,但有时1Gb),但有很多RAM(例如64Gb)。
当将频繁访问的python对象作为单独的cPickle文件存储而不是将所有对象存储在一个大型书架中时,由于linux磁盘缓冲区缓存,IO是否更有效?linux磁盘缓冲区缓存是否使python cPickle比shelve更高效?
在这两种情况下,磁盘缓冲区缓存在效率方面是否运行不同?
可能有成千上万的大文件(通常大约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,OS,文件系统类型,硬件等版本而异。
此外,请注意我的write
和read
函数会生成非常小的文件。您将需要对与您的用例更类似的数据进行测试。
不错的例子,谢谢。我会在我的测试案例中更广泛地运行它并报告回来。 – ricopan 2010-10-31 01:16:45
一如既往,最安全的选择是尝试一下,而不是琢磨这个和那个。 – delnan 2010-10-30 22:31:02
当然,但我想知道python如何与Linux磁盘缓冲区缓存进行交互,这是我一无所知。 – ricopan 2010-10-30 22:33:26
我相信Python不会直接与任何OS缓存进行交互......性能将取决于文件系统本身。只需将pickle的大小作为参数,并运行一些基准。我的直觉告诉我,如果你正在读/写很多东西,你最好用一个架子。如果你正在进行不频繁的读/写操作,请坚持单独的泡菜。 – 2010-10-30 23:39:35