3

我有以下测试代码:

package main

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

type Coll1 struct {
    A string
    B string
    C string
}

type Coll2 struct {
    A *string
    B *string
    C *string
}

var as = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
var bs = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
var cs = "ccccccccccccccccccccccccccccccccc"

func testBM1(b *testing.B) {
    for i := 0; i<b.N; i++ {
        json.Marshal(Coll1{as,bs,cs})
    }
}

func testBM2(b *testing.B) {
    for i := 0; i<b.N; i++ {
        json.Marshal(Coll2{&as,&bs,&cs})
    }
}

func main() {
    fmt.Println(testing.Benchmark(testBM1))
    fmt.Println(testing.Benchmark(testBM2))
}

我希望第二种情况运行得更快,因为它使用指针,因此不必复制字符串,但实际上它的运行速度约为 4250 ns/op,而第一种运行速度接近 2800 ns/op。任何人都可以解释为什么会这样吗?

编辑: Darshan Computing 建议这甚至可能适用于嵌入式结构。一个简单的测试证实了这一点:

package main

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

type Coll1 struct {
    A,B,C string
}

type Coll1Outer struct {
    A,B,C Coll1
}

type Coll2Outer struct {
    A,B,C *Coll2
}

type Coll2 struct {
    A,B,C *string
}

var as = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
var bs = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
var cs = "ccccccccccccccccccccccccccccccccc"

func testBM1(b *testing.B) {
    for i := 0; i<b.N; i++ {
        c := Coll1Outer{ Coll1{as,bs,cs}, 
                         Coll1{as,bs,cs},                
                         Coll1{as,bs,cs} }               
        json.Marshal(c)
    }
}

func testBM2(b *testing.B) {
    for i := 0; i<b.N; i++ {
        c := Coll2Outer{ &Coll2{&as,&bs,&cs},
                         &Coll2{&as,&bs,&cs},            
                         &Coll2{&as,&bs,&cs} }           
        json.Marshal(c)
    }
}

func main() {
    fmt.Println(testing.Benchmark(testBM1))
    fmt.Println(testing.Benchmark(testBM2))
}

对我来说,这表明非指针结构大约需要 12ms/op,而带有指针的结构需要 13ms/op。差别不大,但有趣的是该属性仍然存在。

4

1 回答 1

1

当我分别设置asbs和、和cs时,我注意到 ns/op 的最大百分比差异。当我增加琴弦的长度时,它们会彼此靠近。它们似乎总是大约 1000 ns/op 不同。"a""b""c"

所以我相信正在发生的一切是我的机器上需要 1000 纳秒(你的机器上是 1450 纳秒)来反映和遵循指针。预先传递一个较小的结构似乎并不能抵消这种影响,因为一旦跟随指针,Marshal在生成和返回等效 JSON 的过程中仍然会在内部传递数据。

于 2013-05-31T06:02:13.443 回答