je le code de test suivant:Go: json codage struct avec des pointeurs est plus lent qu'avec des copies?
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))
}
je me attends le second cas, de courir plus vite, car il utilise des pointeurs et ne dispose donc pas de copier les chaînes, mais en fait, il fonctionne à environ 4250 ns/op où la première tourne près de 2800 ns/op. Quelqu'un peut-il faire la lumière sur pourquoi cela pourrait être? Edit: Darshan Computing a suggéré que cela pourrait même être vrai pour les structures intégrées. Un simple test confirme:
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))
}
Pour moi, cela montre la struct non-pointeur prenant environ 12ms/op, tandis que celui des pointeurs prend 13ms/op. Pas une énorme différence, mais c'est intéressant que la propriété tient toujours.
J'ai réécrit votre code pour profiter des fonctionnalités de benchmarking intégrées (voir http://play.golang.org/p/90fYFCSjN9) et j'ai obtenu 3729 ns/op pour le premier et 4600 ns/op pour le second sur win8_64, semble toujours faux, mais les valeurs sont plus proches. – Intermernet
Et, si je remplace les appels 'json.Marshal' par des appels' _ = fmt.Sprintf', j'obtiens respectivement 11990 ns/op et 7098 ns/op (rendant les pointeurs presque 70% plus rapides). Il se passe quelque chose dans la fonction json.Marshall qui ralentit l'utilisation des pointeurs. – Intermernet
Après un peu plus de recherche, je pense que c'est parce que la fonction 'marshal' dans' encoding/json' appelle 'reflect.ValueOf()' sur l'interface d'entrée (http://golang.org/src/pkg/encoding/json/ encode.go? s = 7722: 7964 # L230) qui peut être plus lente si elle doit trouver le type d'une valeur représentée par un pointeur, plutôt que directement sur la valeur itslef. Juste une supposition cependant. – Intermernet