为了账号安全,请及时绑定邮箱和手机立即绑定

为什么在“预热”之后解组 JSON 的速度要快得多?

为什么在“预热”之后解组 JSON 的速度要快得多?

Go
慕的地6264312 2023-03-21 17:33:18
我注意到,当我在 Go HTTP 服务器的上下文中计时 JSON 解组时,即使对于小对象也需要 30,000+ 纳秒。这对我来说似乎很大,所以我运行了一些独立的基准测试,结果令人惊讶地显示每次解组的平均时间约为 500 纳米。为了更深入地研究这个问题,我编写了一个程序,它只对同一个小对象执行一系列解组,这表明第一个解组很慢,而后续的要快得多:package mainimport (    "time"    "fmt"    "encoding/json")var b []bytetype Dog struct {    Age int `json:"Age"`}func unmarshalDog() {    dogCopy := Dog{}    start := time.Now().UnixNano()    json.Unmarshal(b, &dogCopy)    end := time.Now().UnixNano()    fmt.Printf("Time to marshal/unmarshal: %d\n", end-start)}func main() {    // Marshal an object into a byte array which we will repeatedly unmarshal from    d := Dog {        Age: 5,    }    var err error    b, err = json.Marshal(d)    if err != nil {        panic(err)    }    for i := 0; i < 20; i++ {        unmarshalDog()    }    // Allow the goroutines to finish before terminating execution.    time.Sleep(3 * time.Second)}输出:$ go run testJSONPerformance.goTime to marshal/unmarshal: 34127Time to marshal/unmarshal: 1465Time to marshal/unmarshal: 979Time to marshal/unmarshal: 892Time to marshal/unmarshal: 849Time to marshal/unmarshal: 814Time to marshal/unmarshal: 822Time to marshal/unmarshal: 822Time to marshal/unmarshal: 815Time to marshal/unmarshal: 829Time to marshal/unmarshal: 822Time to marshal/unmarshal: 819unmarshalDog()更有趣的是,当我运行同一个程序但在一个单独的 goroutine 中运行每次调用viago unmarshalDog()时,预热现象消失并且平均解组时间长得多:Time to marshal/unmarshal: 36540Time to marshal/unmarshal: 4652Time to marshal/unmarshal: 56959Time to marshal/unmarshal: 3887Time to marshal/unmarshal: 57068Time to marshal/unmarshal: 3519Time to marshal/unmarshal: 37160我还尝试了一个版本,而不是解组相同的字节数组,我每次都编组和解组一个不同的对象(以防某种运行时缓存正在进行)。在这种情况下,结果是一样的。我非常想知道这种明显的“热身”是怎么回事。在 HTTP 服务器的上下文中,每个请求都会得到一个不同的 goroutine,因此每个解组平均来说都非常慢。这似乎不是最理想的,因为显然 Go 有可能在特定上下文中用 1/50 的时间进行解组。所有直觉赞赏!
查看完整描述

1 回答

?
红颜莎娜

TA贡献1842条经验 获得超12个赞

JSON 解组器缓存有关任何类型的第一次解组的信息。该类型的后续解组使用此缓存信息。

缓存在 goroutine 之间共享,但是没有代码来确保只有一个 goroutine 尝试创建第一个缓存值。一旦一个 goroutine 将一个值存储到缓存中,所有新来者都将使用该缓存值。

缓存的代码在这里


查看完整回答
反对 回复 2023-03-21
  • 1 回答
  • 0 关注
  • 87 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信