Mon nouveau message a été inspiré par le dernier quiz go. Faites attention au benchmark [1]:
func BenchmarkSortStrings(b *testing.B) {
s := []string{"heart", "lungs", "brain", "kidneys", "pancreas"}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
sort.Strings(s)
}
}
En guise d'habillage pratique sort.Sort(sort.StringSlice(s))
, il sort.Strings
modifie les données qui lui sont transmises, en les triant, de sorte que tout le monde (au moins, au moins 43% des abonnés Twitter) puisse supposer que cela conduirait à des allocations [allocations sur le tas]. Cependant, au moins dans les versions récentes de Go, c'est le cas et chaque itération de ce benchmark entraînera une allocation. Mais pourquoi?
Comme de nombreux développeurs Go devraient le savoir, les interfaces sont implémentées sous la forme d'une structure à deux mots (machine) . Chaque valeur d'interface contient deux champs: l'un contient le type de valeur stockée par l'interface et l'autre contient un pointeur vers cette valeur. [2]
En pseudocode, cela ressemblerait à ceci:
type interface struct { // , type uintptr // () , data uintptr }
interface.data
, 8 . , , []string
24 : , ; ; (capacity). Go 24 8? , . , []string
24 , *[]string
— 8.
[Escaping]
, sort.Strings
:
func BenchmarkSortStrings(b *testing.B) { s := []string{"heart", "lungs", "brain", "kidneys", "pancreas"} b.ReportAllocs() for i := 0; i < b.N; i++ { var ss sort.StringSlice = s var si sort.Interface = ss // allocation sort.Sort(si) } }
, var si sort.Interface = ss
, var si sort.Interface = &ss
, ss
[3]. , ss
, ? ss
?
, ss
[heap], .
Total: 296.01MB 296.01MB (flat, cum) 99.66% 8 . . func BenchmarkSortStrings(b *testing.B) { 9 . . s := []string{"heart", "lungs", "brain", "kidneys", "pancreas"} 10 . . b.ReportAllocs() 11 . . for i := 0; i < b.N; i++ { 12 . . var ss sort.StringSlice = s 13 296.01MB 296.01MB var si sort.Interface = ss // allocation 14 . . sort.Sort(si) 15 . . } 16 . . }
, , ss
si
(, , , - ). , ss
. , : ? , .
% go test -bench=. sort_test.go goos: darwin goarch: amd64 cpu: Intel(R) Core(TM) i7-5650U CPU @ 2.20GHz BenchmarkSortStrings-4 12591951 91.36 ns/op 24 B/op 1 allocs/op PASS ok command-line-arguments 1.260s
Go 1.16beta1, amd64, 24 [4].
Go 32 .
% go1.15 test -bench=. sort_test.go goos: darwin goarch: amd64 BenchmarkSortStrings-4 11453016 96.4 ns/op 32 B/op 1 allocs/op PASS ok command-line-arguments 1.225s
: Go. , , [size classes].
, , , [] Go 24 . — , . , 24 , 24, . , 24 , , . , , .
, Go 24 , , — , . , . , . ? , .
, , , "", . , 24 , . ? , — [5].
24 , 8 , . 25% "" — , , . ? , 9 , ! - ?
, , . 24- , , , . , — , , - 24- . Go , ( , , , C++). , .
,
, : ? : . , (, ), . .
[6], ( ) . , [7].
, , 9 . , , , 9- . () , , 4. , — . 9 12 . , 3 — , , .
. Go 1.15 24 , ss
32 . Martin Möhrmann Go 1.16 24 , .
[1] , . .
[2] Go. , Go 1.15 . -, .
[3] , sort.StringSlice
, *sort.StringSlice
.
[4] 32 , .
[5] 4G (, , 64 ), , [aligment] [padding] ( , , — . ).
[6] — .
[7] , , .