2015-01-02 7 views
8

私はYAMLやJSONの速度を比較するために、小さなテストケースを作った:YAMLをスピードアップできますか?

import json 
import yaml 
from datetime import datetime 
from random import randint 

NB_ROW=1024 

print 'Does yaml is using libyaml ? ',yaml.__with_libyaml__ and 'yes' or 'no' 

dummy_data = [ { 'dummy_key_A_%s' % i: i, 'dummy_key_B_%s' % i: i } for i in xrange(NB_ROW) ] 


with open('perf_json_yaml.yaml','w') as fh: 
    t1 = datetime.now() 
    yaml.safe_dump(dummy_data, fh, encoding='utf-8', default_flow_style=False) 
    t2 = datetime.now() 
    dty = (t2 - t1).total_seconds() 
    print 'Dumping %s row into a yaml file : %s' % (NB_ROW,dty) 

with open('perf_json_yaml.json','w') as fh: 
    t1 = datetime.now() 
    json.dump(dummy_data,fh) 
    t2 = datetime.now() 
    dtj = (t2 - t1).total_seconds() 
    print 'Dumping %s row into a json file : %s' % (NB_ROW,dtj) 

print "json is %dx faster for dumping" % (dty/dtj) 

with open('perf_json_yaml.yaml') as fh: 
    t1 = datetime.now() 
    data = yaml.safe_load(fh) 
    t2 = datetime.now() 
    dty = (t2 - t1).total_seconds() 
    print 'Loading %s row from a yaml file : %s' % (NB_ROW,dty) 

with open('perf_json_yaml.json') as fh: 
    t1 = datetime.now() 
    data = json.load(fh) 
    t2 = datetime.now() 
    dtj = (t2 - t1).total_seconds() 
    print 'Loading %s row into from json file : %s' % (NB_ROW,dtj) 

print "json is %dx faster for loading" % (dty/dtj) 

、結果は次のとおりです。

Does yaml is using libyaml ? yes 
Dumping 1024 row into a yaml file : 0.251139 
Dumping 1024 row into a json file : 0.007725 
json is 32x faster for dumping 
Loading 1024 row from a yaml file : 0.401224 
Loading 1024 row into from json file : 0.001793 
json is 223x faster for loading 

私はUbuntuの12.04でlibyaml CライブラリとPyYAMLと3.11を使用しています。 jsonはyamlよりもシンプルですが、jsonとyamlの間の223倍の比率で私の設定が正しいかどうかは疑問です。

同じスピードレシオはありますか?
yaml.load()をスピードアップするにはどうすればよいですか?

答えて

12

あなたはおそらく、データ構造のPythonの構文がであり、JSONの構文に似ていると思われます。です。何が起こっている

はPythonのjsonライブラリが(少しoversimplifyする)"'を交換し、あちこちで,を削除、Pythonの組み込みデータ型directly into text chunksエンコードです。

一方、pyyamlconstruct a whole representation graphになり、それを文字列にシリアル化します。

読み込み時に同じ種類のものが後方に起こることがあります。

yaml.load()を高速化する唯一の方法は、新しいLoaderを書くが、私はそれがパフォーマンスの大きな飛躍可能性を疑う、あなたがあなた自身の単一目的のソートのYAMLパーサを書くために喜んでいる場合を除いて、服用することです考慮しthe following comment:それは同じ オブジェクトに複数の参照を表現することができる汎用シリアル化 形式であるため

YAMLグラフを構築します。オブジェクトが繰り返されず、基本タイプのみが表示される場合は、 jsonシリアライザを使用できますが、それでも有効なYAMLです。

- 私が前に言った何UPDATE

は真のままですが、あなたはLinuxを実行している場合Yaml解析を高速化する方法があります。デフォルトでは、PythonのyamlはPythonパーサーを使用します。あなたはPyYamlCパーサーを使いたいと言わなければなりません。あなたはそれをこのように行うことができます

:だけでなくLibYaml

$ apt-get install yaml-cpp-dev 

そしてPyYaml:そうするためには

import yaml 
from yaml import CLoader as Loader, CDumper as Dumper 

dump = yaml.dump(dummy_data, fh, encoding='utf-8', default_flow_style=False, Dumper=Dumper) 
data = yaml.load(fh, Loader=Loader) 

を、あなたはapt-getを持つ例えば、yaml-cpp-devをインストールする必要があります。しかし、それはすでにあなたの出力に基づいています。

私はOS Xを実行しているとbrewyaml-cpp-devをインストールするいくつかの問題を持っていますが、PyYaml documentationに従うならば、彼らはパフォーマンスが大幅に良くなることはかなりはっきりしているので、私は今それをテストすることはできません。

+1

yaml.myを使用した読み込みはまだ12倍遅く、サンプルは600,000の空の辞書のリストです。 Yamlは余分な時間をほとんど必要としない、わずかにより洗練された構文解析を除いて、何も追加する必要はありません。 – codeshot

+1

Macの場合:brew install yaml-cpp libyaml –

+0

ジバンあなたは血の伝説です。私は物事をスピードアップするためにC++でいくつかのPythonコードを書き直そうとしていました。私の6MBのyamlファイルは、標準のyamlローダーを使用して53秒、CLoaderを使用して3秒しかかかりませんでした。 – nevelis

0

はい、JSONの方が高速です。合理的なアプローチは、YAMLをJSONに変換することです。あなたはルビーを気にしない場合は、大きなスピードアップを取得し、yamlが完全にインストール捨てることができます。

load_yaml_file: 0.95 s 
yaml.load: 7.53 s 

そして1Mレコードの:

ここ

import commands, json 
def load_yaml_file(fn): 
    ruby = "puts YAML.load_file('%s').to_json" % fn 
    j = commands.getstatusoutput('ruby -ryaml -rjson -e "%s"' % ruby) 
    return json.loads(j[1]) 

は100Kレコードの比較であります

load_yaml_file: 11.55 s 
yaml.load: 77.08 s 

とにかくyaml.loadの使用を強くお勧めする場合は、他のソフトウェアとの競合を避けるためにvirtualenvに入れてください。

関連する問題