ここに少し、そこに少し-そして今あなたはすでにメモリが実際にどのように機能するかについて話している

私の新しい投稿は、最新の囲碁クイズに触発されました。ベンチマークに注意してください[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)
        }
}
      
      





周りの便利なラッパーとしてsort.Sort(sort.StringSlice(s))



、それはsort.Strings



誰もが(少なくとも、Twitterの加入者の少なくとも43%)が、これが割り当て[ヒープ上の割り当て]につながることを想定できそうということ、それを並べ替え、それに渡されたデータを変更します。ただし、少なくとも最近のバージョンのGoでは、これが当てはまり、このベンチマークを繰り返すたびに1つの割り当てが発生します。しかし、なぜ?







多くのGo開発者が知っておくべきことですが、インターフェースは2つの(マシン)ワード構造として実装されています。各インターフェイス値には2つのフィールドが含まれます。1つはインターフェイスによって格納された値のタイプを含み、もう1つはその値へのポインタを含みます。[2]







擬似コードでは、次のようになります。







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] , , .








All Articles