DBM,File Readはどちらが早いか比較してみた。

たとえば、1kくらいのファイルが、ひとつのディレクトリーに大量にあった場合、ファイルリードが遅くなってくし、大量にiノードを消費してしまう。それを防ぐために、たとえば、20万ファイルくらい、同一のディレクトリにあった場合、それをファイルとして保存せずに、ひとつにDBMにkey=ファイル名、value=ファイル内容にしてしまうことも可能だ。 複数のファイルをひとつのDBMに格納した場合、速度低下はあるのだろうか?

28万ファイルをひとつのDBMに突っ込んでみた。

28万ファイルのxmlをひとつのDBMにつっこんみた 大体1Gぐらいの大きさ。dbmはdbmhashである。

key=filename value=fileの内容になっている。

DBM,ファイルリードを比べてみる。

time=5851 func=<function gen_smlist at 0xb7cc54fc>
smidsize=17979
time=174842 func=<function benchmark_dbm at 0xb7cbf7d4>
time=269485 func=<function benchmark_file at 0xb7cc548c>

178秒(DBM)対269秒(FileRead)になっている。大体、2/3位になる。

結論

小さなファイルをたくさん使う場合は、ファイルをそのまま保存するのではなく、DBMに入れるのもあり。

ソース

#!/usr/bin/python
# -*- coding:utf-8 -*-

import anydbm
from glob import glob
import os
import json
import time
import random

src='../nicoran-data/thumbinfo/*.xml'
json_src='../nicoran-data/json/*.json'
src_dir='../nicoran-data/thumbinfo/'

def import_dbm():
    l=glob(src)
    dbm=anydbm.open('thumbinfo.dbm','c')
    for i,f in enumerate(l):
        smid=os.path.basename(f).split('.')[0]
        dbm[smid]=open(f).read()
        if i%1000==0:
            print i,smid,f
    dbm.close()
def import_test():
    dbm=anydbm.open('thumbinfo.dbm','r')
    print dir(dbm)
    k=dbm.items()
    print len(k)

def time_profile(f):
    def inner_time(*args,**keys):
        t1=time.time()
        r=f(*args,**keys)
        t1=time.time()-t1
        print 'time=%d func=%s' % (t1*1000,f)
        return r
    return inner_time

   
@time_profile    
def benchmark_dbm(smlist):
    dbm=anydbm.open('thumbinfo.dbm','r')
    for smid in smlist:
        r=dbm[smid]
        len(r)
    dbm.close()

@time_profile    
def benchmark_file(smlist):
    for smid in smlist:
        smid=smid.encode('utf-8')
        smfile=src_dir+smid+'.xml'
        if os.path.isfile(smfile):
            a=open(smfile).read()
            k=len(a)

@time_profile
def gen_smlist(json_src):
    smlist=set()
    jds=glob(json_src)
    random.shuffle(jds)
    for jd in jds[:10]:
        jd=json.loads(open(jd).read())
        for a in jd:
            for l in a['ranklist']:
                smid=l['smid']
                smlist.add(smid.encode('utf-8'))
    return smlist

def main():
    #import_dbm()
    #mport_test()
    smlist=gen_smlist(json_src)
    print 'smidsize=%d' % len(smlist)
    benchmark_dbm(smlist)
    benchmark_file(smlist)

if __name__=='__main__':main()

添付ファイル: fileimport_dbm_test.py 6644件 [詳細]

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-02-01 (日) 14:38:23 (3365d)