Mi nueva publicación se inspiró en la última prueba de go. Preste atención al punto de referencia [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)
}
}
Como un envoltorio conveniente sort.Sort(sort.StringSlice(s))
, sort.Strings
modifica los datos que se le pasan, clasificándolos, de modo que no todos (al menos, al menos el 43% de los suscriptores de Twitter) puedan asumir que esto conduciría a asignaciones [asignaciones en el montón]. Sin embargo, al menos en las versiones recientes de Go, este es el caso y cada iteración de este punto de referencia provocará una asignación. ¿Pero por qué?
Como muchos desarrolladores de Go deberían saber, las interfaces se implementan como una estructura de dos palabras (de máquina) . Cada valor de la interfaz contiene dos campos: uno contiene el tipo de valor almacenado por la interfaz y el otro contiene un puntero a ese valor. [2]
En pseudocódigo, se vería así:
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] , , .