هل تجعل ذاكرة التخزين المؤقت لـ Linux Disk Buffer Python cpickle أكثر كفاءة من الرفوف؟

StackOverflow https://stackoverflow.com/questions/4060937

سؤال

هل IO أكثر كفاءة ، نظرًا لذاكرة التخزين المؤقت لـ Linux Disk ، عند تخزين كائنات Python التي يتم الوصول إليها بشكل متكرر كملفات cpickle منفصلة بدلاً من تخزين جميع الكائنات في رف كبير واحد؟

هل تعمل ذاكرة التخزين المؤقت للمخزن المؤقت للقرص بشكل مختلف في هذين السيناريوهين فيما يتعلق بالكفاءة؟

قد يكون هناك الآلاف من الملفات الكبيرة (عمومًا حوالي 100 ميجابايت ، ولكن في بعض الأحيان 1 جيجابايت) ، ولكن الكثير من ذاكرة الوصول العشوائي (مثل 64 جيجابايت).

هل كانت مفيدة؟

المحلول

لا أعرف أي طريقة نظرية لتحديد الطريقة أسرع ، وحتى لو فعلت ذلك ، لست متأكدًا من أنني سأثق بها. لذلك دعونا نكتب بعض التعليمات البرمجية ونختبرها.

إذا قمنا بتعبئة مديري المخلل/الرفوف في الفصول مع واجهة مشتركة ، فسيكون من السهل تبديلهم داخل وخارج التعليمات البرمجية الخاصة بك. لذا ، إذا كنت في بعض الأحيان تكتشف واحدة أفضل من الآخر (أو اكتشف بطريقة أفضل) ، كل ما عليك فعله هو كتابة فصل مع نفس الواجهة وستتمكن من توصيل الفصل الجديد في الكود الخاص بك القليل جدا من التعديل لأي شيء آخر.

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(...)

بينما كنت تستخدم شيلفاناجر مثل هذا:

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 وظائف إنشاء ملفات صغيرة جدا. ستحتاج إلى اختبار هذا على البيانات بشكل أكثر تشابهًا لحالة الاستخدام الخاصة بك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top