首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么在“热身”之后解封JSON要快得多?

为什么在“热身”之后解封JSON要快得多?
EN

Stack Overflow用户
提问于 2018-08-23 16:44:34
回答 1查看 116关注 0票数 0

我注意到,当我在Go服务器的上下文中执行JSON解组时,即使对于小对象,也要花费30,000+纳秒时间。这对我来说似乎很大,所以我运行了一些独立的基准,令人惊讶的是,每个解组的平均时间是500 nanos。为了更深入地研究这一点,我编写了一个程序,它只在同一个小对象上执行一系列的解组操作,这表明第一个解编组是缓慢的,而后续的解组则要快得多:

代码语言:javascript
运行
复制
package main

import (
    "time"
    "fmt"
    "encoding/json"
)

var b []byte

type 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)
}

输出:

代码语言:javascript
运行
复制
$ go run testJSONPerformance.go
Time to marshal/unmarshal: 34127
Time to marshal/unmarshal: 1465
Time to marshal/unmarshal: 979
Time to marshal/unmarshal: 892
Time to marshal/unmarshal: 849
Time to marshal/unmarshal: 814
Time to marshal/unmarshal: 822
Time to marshal/unmarshal: 822
Time to marshal/unmarshal: 815
Time to marshal/unmarshal: 829
Time to marshal/unmarshal: 822
Time to marshal/unmarshal: 819

更有趣的是,当我运行相同的程序,但通过unmarshalDog()在单独的go unmarshalDog()中运行每个调用时,热身现象消失了,平均解组时间要长得多:

代码语言:javascript
运行
复制
Time to marshal/unmarshal: 36540
Time to marshal/unmarshal: 4652
Time to marshal/unmarshal: 56959
Time to marshal/unmarshal: 3887
Time to marshal/unmarshal: 57068
Time to marshal/unmarshal: 3519
Time to marshal/unmarshal: 37160

我还尝试了一个版本,在这个版本中,我没有对相同的字节数组进行解封,而是每次封送和解封一个不同的对象(以防出现某种运行时缓存)。这个案例的结果是一样的。

我很好奇这个明显的“热身”是怎么回事。在HTTP服务器的上下文中,每个请求都有一个不同的goroutine,因此每个解组的平均速度都很慢。考虑到Go显然有可能在某一特定情况下在1/50的时间内进行解组,这似乎不太理想。所有的直觉都被欣赏了!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-24 13:31:13

JSON解组器缓存任何类型的第一个解封组的信息。类型的后续反封送处理使用此缓存信息。

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

缓存的代码是这里

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51990634

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档