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

2 番目のケースはポインターを使用しているため文字列をコピーする必要がないため、より高速に実行されると予想されますが、実際には約 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"a""b"、およびにそれぞれ設定すると、ns/op の最大のパーセンテージの違いに気付きまし"c"た。糸の長さを長くしていくと、糸同士が近づきます。それらは常に約 1000 ns/op 異なるようです。

つまり、私のマシンでは 1000 ns (あなたのマシンでは 1450 ナノ秒) かかるだけで、ポインターを反映して追跡することができます。より小さな構造体を前もって渡しても、この効果は打ち消されないようです。これは、ポインターが追跡Marshalされると、同等の JSON を生成して返すプロセスで内部的にデータを渡し続けるためです。

于 2013-05-31T06:02:13.443 に答える