C wrapper Python library Json Slicer 比纯 Python ijson 库慢



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

当我在 5GB 大小的深度嵌套 JSON 文件上使用这两个库时,预计 Json Slicer 作为 YAJL (https://lloyd.github.io/yajl/( 上的包装器将比纯 Python 实现的 ijson 执行得更快。但是,Json Slicer 花费的时间是 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。在执行脚本期间未使用多处理。

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

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

默认情况下,一旦初始模式匹配发生,ijson 就会将子文档复制到 Python 字典/列表中。这会产生成本。如果你想用Python操作文档的一部分(而不是提取标量/字符串(,你仍然需要转换。使用C实现进行解析时,这需要将C变量转换为Python变量。

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

Jsonslicer(对我来说(对于简单的提取任务来说非常快,但随着提取复杂性的增加,它也会遇到类似的限制。我有一个 970 MB 的未压缩 JSON 文件,其中包含一个文档列表。就我而言,从 3rd 级属性中进行选择的琐碎字符串如下所示:

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
  • 艾森(纯蟒蛇( - 686秒
  • JSONSLICER - 15s

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

在这种情况下,如果我在不更改交互的情况下深入挖掘两层,我会得到:

  • 艾森 - 350s
  • 艾森(纯蟒蛇( - 667秒
  • JSON 切片器 - 16s

jsonslicer 会放慢速度,需要检查更多内容,而 IJSON 也会这样做,但通过建模较小的文档部分来节省时间。更复杂的用途会改变平衡。证明从 C 转换为 Python 是你看不见的代码变慢的原因会很困难,但它可能会有所贡献!

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

历史上没有yajl2_c后端,所以当人们提到"C后端"时,实际上是yajl2_cffi后端。最重要的是,人们可能仍然认为 ijson 默认为python后端。

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

最新更新