我做了一个小测试用例来比较YAML和JSON的速度:
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
我在ubuntu12.04上使用PyYAML 3.11和libyaml C库。我知道json比yaml简单得多,但是json和yaml之间的比率是223x,我想知道我的配置是否正确。
你们有相同的速比吗?
如何加快yaml.load()
的速度?
5条答案
按热度按时间mmvthczy1#
您可能已经注意到Python的数据结构语法与JSON的语法非常相似。
实际上,Python的
json
库编码了Python的内置数据类型directly into text chunks,将'
替换为"
,并在各处删除,
(有点过于简化)。另一方面,
pyyaml
在将其序列化为字符串之前必须构造一个完整的表示图。同样的事情必须在加载时向后发生。
加速
yaml.load()
的唯一方法是编写一个新的Loader
,但我怀疑这可能是性能上的巨大飞跃,除非您愿意编写自己的单一用途的YAML
解析器,并考虑以下评论:YAML构建了一个图形,因为它是一个通用的序列化格式,能够表示对同一个对象的多个引用。如果你知道没有对象是重复的,只有基本类型出现,你可以使用json序列化器,它仍然是有效的YAML。
我之前说的仍然是正确的,但是如果你运行的是
Linux
,有一种方法可以加速Yaml
解析,默认情况下,Python的yaml
使用Python解析器,你必须告诉它你想使用PyYaml
C
解析器。您可以这样做:
为此,您需要安装
yaml-cpp-dev
(包后来重命名为libyaml-cpp-dev
),例如使用apt-get:PyYaml
和LibYaml
也是一样的,但是根据你的输出已经是这样了。我现在不能测试它,因为我运行的是OSX,
brew
在安装yaml-cpp-dev
时遇到了一些麻烦,但如果你按照PyYaml documentation,他们很明显性能会好得多。6uxekuva2#
作为参考,我比较了几种人类可读的格式,Python的yaml阅读器确实是“迄今为止”最慢的(注意下图中的对数缩放)。如果您想要速度,那么您需要JSON加载器之一,例如orjson:
用于重现绘图的代码:
k3fezbri3#
是的。
这里的其他回答是"使用
CLoader
",这是一个很好的提示,但是如果你没有使用任何定制类(YAML中的!!foo
标记),你可以通过使用CBaseLoader
而不是普通的CLoader
来挤出另外大约20%的时间。我有一个脚本,从约2分37秒到约2分7秒的变化。
应该就像这样简单:
qoefvg9y4#
这里还没有提到的还有CSafeLoader
C
类实现。我发现它比
CLoader
稍微快一点(至少对于50kb
下的小文件来说,两者都比python实现快15倍左右)由于noted above,
CBaseLoader
比其他C
类快大约20%
,这是由于:BaseLoader(stream)不解析或支持任何标签,只构造基本的Python对象:列表、字典和Unicode字符串。
CBaseLoader
无法识别yaml
中的boolean
。8i9zcol25#
是的,我也注意到JSON要快得多。所以一个合理的方法是先把YAML转换成JSON。如果你不介意ruby,那么你可以得到一个很大的加速,并且完全抛弃
yaml
安装:以下是10万条记录的比较:
对于1M条记录:
如果您坚持使用yaml.load,请记住将其放在virtualenv中,以避免与其他软件冲突。