Je travaille souvent avec des tranches de structs. Voici un exemple pour une telle structure:
type MyStruct struct {
val1, val2, val3 int
text1, text2, text3 string
list []SomeType
}
Je définis donc mes tranches comme suit:
[]MyStruct
Disons que j'ai environ un million d'éléments là-dedans et que je travaille beaucoup avec la tranche:
Ma compréhension est que cela conduit à beaucoup de remaniements autour de la structure réelle. L'alternative est de créer une tranche de pointeurs vers la structure:
[]*MyStruct
Maintenant, les structures restent où elles sont et nous ne traitons que des pointeurs qui, je suppose, ont une empreinte plus petite et rendront donc mes opérations plus rapides. Mais maintenant, je donne beaucoup plus de travail au ramasse-miettes.
Je suis juste devenu curieux à ce sujet. Ran quelques repères:
type MyStruct struct {
F1, F2, F3, F4, F5, F6, F7 string
I1, I2, I3, I4, I5, I6, I7 int64
}
func BenchmarkAppendingStructs(b *testing.B) {
var s []MyStruct
for i := 0; i < b.N; i++ {
s = append(s, MyStruct{})
}
}
func BenchmarkAppendingPointers(b *testing.B) {
var s []*MyStruct
for i := 0; i < b.N; i++ {
s = append(s, &MyStruct{})
}
}
Résultats:
BenchmarkAppendingStructs 1000000 3528 ns/op
BenchmarkAppendingPointers 5000000 246 ns/op
À retenir: nous sommes en nanosecondes. Probablement négligeable pour les petites tranches. Mais pour des millions d'opérations, c'est la différence entre les millisecondes et les microsecondes.
Btw, j'ai essayé de réexécuter le benchmark avec des tranches qui ont été préallouées (avec une capacité de 1000000) pour éliminer la surcharge de append () en copiant périodiquement le tableau sous-jacent. L'ajout de structures a chuté de 1000 ns, l'ajout de pointeurs n'a pas changé du tout.
Pouvez-vous fournir des directives générales sur le moment de travailler directement avec des structures par rapport au moment de travailler avec des pointeurs vers des structures?
Non, cela dépend trop de tous les autres facteurs que vous avez déjà mentionnés.
La seule vraie réponse est: comparer et voir. Chaque cas est différent et toute la théorie du monde ne fait aucune différence lorsque vous avez des horaires réels avec lesquels travailler.
(Cela dit, mon intuition serait d'utiliser des pointeurs, et éventuellement un sync.Pool
pour aider le garbage collector: http://golang.org/pkg/sync/#Pool )