2010-10-30 102 views
3

當將頻繁訪問的python對象作爲單獨的cPickle文件存儲而不是將所有對象存儲在一個大型書架中時,由於linux磁盤緩衝區緩存,IO是否更有效?linux磁盤緩衝區緩存是否使python cPickle比shelve更高效?

在這兩種情況下,磁盤緩衝區緩存在效率方面是否運行不同?

可能有成千上萬的大文件(通常大約100Mb,但有時1Gb),但有很多RAM(例如64Gb)。

+1

一如既往,最安全的選擇是嘗試一下,而不是琢磨這個和那個。 – delnan 2010-10-30 22:31:02

+0

當然,但我想知道python如何與Linux磁盤緩衝區緩存進行交互,這是我一無所知。 – ricopan 2010-10-30 22:33:26

+0

我相信Python不會直接與任何OS緩存進行交互......性能將取決於文件系統本身。只需將pickle的大小作爲參數,並運行一些基準。我的直覺告訴我,如果你正在讀/寫很多東西,你最好用一個架子。如果你正在進行不頻繁的讀/寫操作,請堅持單獨的泡菜。 – 2010-10-30 23:39:35

回答

2

我不知道任何理論方法來決定哪種方法更快,即使我做了,我也不確定我會信任它。所以讓我們編寫一些代碼並對其進行測試。

如果我們將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,文件系統類型,硬件等版本而異。

此外,請注意我的writeread函數會生成非常小的文件。您將需要對與您的用例更類似的數據進行測試。

+0

不錯的例子,謝謝。我會在我的測試案例中更廣泛地運行它並報告回來。 – ricopan 2010-10-31 01:16:45