Un poco de bytes aquí, un poco allí, y ahora ya estás hablando de cómo funciona realmente la memoria.

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








All Articles