Mein neuer Beitrag wurde vom neuesten Go-Quiz inspiriert. Achten Sie auf den 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)
}
}
Als bequemer Wrapper um sort.Sort(sort.StringSlice(s))
, es sort.Strings
ändert die an sie übergebenen Daten, es sortiert wird , so dass nicht jeder (zumindest, mindestens 43% der Twitter - Abonnent) annehmen könnte , dass dies auf Zuweisungen führen würde [Zuweisungen auf dem Heap]. Zumindest in neueren Versionen von Go ist dies jedoch der Fall und jede Iteration dieses Benchmarks führt zu einer Zuordnung. Aber warum?
Wie viele Go-Entwickler wissen sollten, werden Schnittstellen als Zwei-Maschinen- Struktur implementiert . Jeder Schnittstellenwert enthält zwei Felder: eines enthält den von der Schnittstelle gespeicherten Wertetyp und das andere enthält einen Zeiger auf diesen Wert. [2]
Im Pseudocode würde es so aussehen:
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] , , .