當將頻繁訪問的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