Go与JavaScript的JSON解析比较

6
最近,我需要解析Chrome Web浏览器在其开发工具中记录事件时生成的JSON,并从中获取一些时间数据。Chrome可以在很短的时间内产生大量数据,因此我最初构建的Ruby解析器非常慢。
由于我正在学习Go,所以我决定编写Go和JavaScript/Node脚本并进行比较。
JSON文件的最简单形式是我在this Gist中拥有的内容。它包含代表发送到获取页面的请求的事件和代表响应的事件。通常,有大量额外的数据需要筛选。这是一个问题,但不是我在这个问题中担心的问题。
我写的JavaScript脚本在这里,我写的Go程序在这里。这是我用Go写的第一个有用的东西,所以我确定它肯定存在各种问题。但是,我注意到的一件事情是,在解析大型JSON文件方面,它比JavaScript要慢得多

使用119Mb的JSON文件时在Go中的时间:

$ time ./parse data.json
= 22 Requests
  Min Time:      0.77
  Max Time:      0.77
  Average Time:  0.77
./gm data.json  4.54s user 0.16s system 99% cpu 4.705 total

在JavaScript/Node中处理一个大小为119Mb的JSON文件所需时间:

$ time node parse.js data.json
= 22 Requests
  Min Time: 0.77
  Max Time: 0.77
  Avg Time: 0.77
node jm.js data.json  1.73s user 0.24s system 100% cpu 1.959 total

在这个例子中,最小/最大/平均时间都是相同的,因为我复制了JSON对象以获得非常大的数据集,但这与问题无关。
我很好奇,是JavaScript / Node仅仅比Go更快地解析JSON(这并不特别令人惊讶),还是我在Go程序中做错了什么。此外,我也很好奇我在一般情况下在Go程序中做错了什么,因为我确定它有很多错误。
请注意,虽然这两个脚本做了更多的工作,但在程序中肯定是Go的json.Unmarshal()增加了很多时间。
更新:
我添加了一个Ruby脚本
$ ruby parse.rb
= 22 Requests
  Min Time: 0.77
  Max Time: 0.77
  Avg Time: 0.77
ruby parse.rb  4.82s user 0.82s system 99% cpu 5.658 total

仅作术语说明,“解析”是在调用JSON.parse()或Go的json.unMarshal()时发生的。其余工作只是遍历生成的数据结构。 - Pointy
2
@Pointy 我非常清楚这一点。在 Go 中,json.Unmarshal() 比 JavaScript 中的 JSON.parse() 慢得多(或者看起来是这样)。你是对的,在某些地方我应该使用不同的动词。 :) - clem
@Pointy,顺便说一句,我添加了一个 Ruby 版本。大多数情况下,Go 版本只快了一秒钟。 - clem
@Mostafa 我可能应该剪掉所有额外的冗余代码,但我运行了单独的测试,在我的Go程序中只是将其解组成结构体(没有循环,只是解析),时间差异仍然大致相同。 - clem
1
@Mostafa 请参见:https://gist.github.com/jclem/5979042 - clem
显示剩余8条评论
1个回答

10

使用Go语言时,你将JSON解析为静态类型结构。而使用JS和Ruby时,则会将其解析成散列表。

为了将JSON解析为您定义的结构,json包需要找出它们字段的名称和类型。为此,它使用了reflect包,这比直接访问这些字段要慢得多。

根据您解析后对数据执行的操作,额外的解析时间可能会值回本。Go数据结构使用的内存比哈希表少,并且访问速度更快。因此,如果您对数据进行了大量处理,则节省的处理时间可能会超过额外的解析时间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接