4

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

就效率而言,磁盘缓冲区缓存在这两种情况下的运行方式是否不同?

可能有数千个大文件(通常约为 100Mb,但有时为 1Gb),但 RAM 很大(例如 64 Gb)。

4

1 回答 1

3

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

如果我们将 pickle/shelf 管理器打包到具有公共接口的类中,那么将它们换入和换出代码将很容易。因此,如果在将来某个时候你发现一个比另一个更好(或发现一些更好的方法),你所要做的就是编写一个具有相同接口的类,你就可以将新类插入到你的代码中对其他任何东西的修改很少。

测试.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函数会生成非常小的文件。您需要在与您的用例更相似的数据上对此进行测试。

于 2010-10-31T00:13:29.327 回答