* DBM,File Readはどちらが早いか比較してみた。 [#k238dc2b]
たとえば、1kくらいのファイルが、ひとつのディレクトリーに大量にあった場合、ファイルリードが遅くなってくし、大量にiノードを消費してしまう。それを防ぐために、たとえば、20万ファイルくらい、同一のディレクトリにあった場合、それをファイルとして保存せずに、ひとつにDBMにkey=ファイル名、value=ファイル内容にしてしまうことも可能だ。
複数のファイルをひとつのDBMに格納した場合、速度低下はあるのだろうか?
** 28万ファイルをひとつのDBMに突っ込んでみた。 [#z5831f03]
28万ファイルのxmlをひとつのDBMにつっこんみた 大体1Gぐらいの大きさ。dbmはdbmhashである。
key=filename value=fileの内容になっている。
** DBM,ファイルリードを比べてみる。 [#z62c2eb7]
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位になる。
** 結論 [#i88c4175]
小さなファイルをたくさん使う場合は、ファイルをそのまま保存するのではなく、DBMに入れるのもあり。
** ソース [#u05b0c95]
#!/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()