C包装Python库Json切片器比纯Python ijson库慢

2024-10-03 09:17:11 发布

您现在位置:Python中文网/ 问答频道 /正文

根据官方文档(https://pypi.org/project/jsonslicer/),Json切片器的基本配置每秒产生586.5K个对象,后端使用Python的ijson每秒产生32.2K个对象,而使用C后端(ijson.yajl2_cffi)的ijson每秒产生75.7Kobjects

当我在5GB大小的深度嵌套JSON文件上使用这两个库时,JSON切片器作为YAJL(https://lloyd.github.io/yajl/)上的包装器,其执行速度比纯Python实现的ijson更快。然而,Json切片器花费的时间是607.8014905452728秒,而ijson花费的时间是308.19292974472046秒

根据各种来源(https://lpetr.org/2016/05/30/faster-json-parsing-python-ijson/http://explique.me/Ijson/),使用C后端的ijson应该比使用纯Python后端的ijson工作得更快。但是,ijson使用C后端所花费的时间为2016.68796280378929秒

在不同场合对不同大小的Json文件集多次运行时,会观察到这种行为

我的系统配置是带有20GB RAM的英特尔i7。脚本执行期间未使用多处理

有人能解释一下这种奇怪行为的根本原因吗?也请让我知道一个解决办法


Tags: 文件对象文档httpsorgprojectpypijson
2条回答

所有这些库和实现都执行某种模式匹配,以查找要检查的文件部分。然后必须对所选元素执行操作,通常是将内容升级到Python数据结构中

默认情况下,一旦发生初始模式匹配,ijson就会将子文档复制到Python dict/list中。这要付出代价。如果您想用Python操作文档的一部分(而不是提取标量/字符串),仍然需要转换。如果使用C实现进行解析,则必须将C变量转换为Python变量

在处理必须大量加载的深层数据结构时,您可能会发现用C解析文件的好处与转换为Python的成本相比相形见绌,因此纯Python实现绕过了一些转换成本

jsonslicer(对我来说)对于简单的提取任务来说速度非常快,但随着提取复杂性的增加,它也会遇到类似的限制。我有一个970MB的未压缩JSON文件,其中包含一个文档列表。在我的例子中,从第三级属性中选择一个简单的字符串如下所示:

with gzip.open('big_docs.json.gz') as file:
for thing in JsonSlicer(file, (None, 'key')):
    # print(thing)
    if thing == 'special_value':
        pass


with gzip.open('big_docs.json.gz') as file:
    for thing in ijson.items(file, 'item'):
        if thing['key'] == 'special_value':
            pass
  • ijson(使用默认的C绑定)-363s
  • ijson(纯Python)-686s
  • jsonslicer-15s

在这种不公平的比较中,jsonslicer能够以几乎零的成本避免将字符串以外的任何东西转换为Python,因此结果非常快。我天真的ijson用法必须做更多的工作

在本例中,如果我在不改变交互的情况下深入挖掘两层,我会得到:

  • ijson-350s
  • ijson(纯python)-667s
  • jsonslicer-16s

jsonslicer的速度稍慢,需要检查的内容更多,而ijson也会这样做,但通过对较小的文档节进行建模来获得时间。更复杂的用途会改变平衡。证明从C到Python的转换是你看不见的代码变慢的原因是困难的,但这可能是有帮助的

请注意,由于2.4 ijson有一个新的yajl2_c后端,全部用C编写(即不使用cffi或ctypes),它比其他后端快约10倍。由于2.5,这是默认情况下选择的,如果在您的安装中出现(可能是您的情况,因此您看到了更快的执行)。从2.6开始,有一个新的kvitems方法可以避免构造完整的对象并迭代其成员,这在某些情况下很有用

历史上没有yajl2_c后端,所以当人们提到“C后端”时,实际上是yajl2_cffi后端。除此之外,人们可能仍然认为ijson默认使用python后端

所以要回答您的问题:您可能正在使用yajl2_c后端运行ijson,并且运行速度比JsonSlicer快

相关问题 更多 >