Sedikit byte di sini, sedikit di sana - dan sekarang Anda sudah berbicara tentang bagaimana sebenarnya memori bekerja

Posting baru saya terinspirasi oleh kuis go terbaru. Perhatikan tolok ukur [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)
        }
}
      
      





Sebagai pembungkus yang nyaman sort.Sort(sort.StringSlice(s))



, itu sort.Strings



memodifikasi data yang diteruskan kepadanya, menyortirnya, sehingga tidak semua orang (setidaknya, setidaknya 43% dari pelanggan twitter) dapat berasumsi bahwa ini akan mengarah pada alokasi [alokasi di heap]. Namun, setidaknya dalam versi terbaru Go, ini masalahnya dan setiap iterasi dari tolok ukur ini akan menyebabkan satu alokasi. Tapi kenapa?







Seperti yang harus diketahui oleh banyak pengembang Go, antarmuka diimplementasikan sebagai dua struktur kata (mesin) . Setiap nilai antarmuka berisi dua bidang: satu berisi tipe nilai yang disimpan oleh antarmuka, dan yang lainnya berisi penunjuk ke nilai itu. [2]







Dalam pseudocode, akan terlihat seperti ini:







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