performance - Orden del código y rendimiento
struct slice (2)
La ejecución de cualquier código por primera vez puede tener cierta sobrecarga (significativa), por ejemplo, el código relacionado puede cargarse, muchas cosas pueden diferirse hasta que sean necesarias (por ejemplo, memorias intermedias internas). Ejecutar lo mismo nuevamente puede llevar mucho menos tiempo, la diferencia puede ser incluso de varios órdenes de magnitud .
Siempre que desee medir los tiempos de ejecución, debe ejecutarlo muchas veces, medir el tiempo de ejecución de las ejecuciones múltiples y calcular el tiempo promedio. También es una buena idea excluir las primeras (algunas) ejecuciones del cálculo por los motivos mencionados anteriormente.
En Go, lo mejor y más fácil es usar archivos de prueba y funciones de referencia.
Lea el paquete de
testing
para obtener más detalles y ejemplos.
Su caso puede ser comparado de esta manera:
package main
import "testing"
type abc struct {
a, b, c, d int
}
func BenchmarkSlice(b *testing.B) {
a := make([]int, 4)
for i := 0; i < b.N; i++ {
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
}
}
func BenchmarkStruct(b *testing.B) {
a := abc{}
for i := 0; i < b.N; i++ {
a.a = 1
a.b = 2
a.c = 3
a.d = 4
}
}
go test -bench .
en un archivo como
something_test.go
, ejecútelo con
go test -bench .
.
Salida:
BenchmarkSlice-4 2000000000 1.24 ns/op
BenchmarkStruct-4 2000000000 0.31 ns/op
Puedes ver que usar una estructura es aproximadamente 4 veces más rápido. Obtendrá resultados similares (muy cercanos) si reordena las funciones de referencia.
Quería encontrar cuál es más rápido: struct vs array. Así que escribí un código GO en el que escribo 4 valores int (1,2,3 y 4) para los miembros de una estructura y luego en una matriz de longitud 4. Intenté encontrar el tiempo que toma escribir.
Caso 1: Primero, escribo valores en una estructura y luego en una matriz. Aquí encontré que la matriz es más rápida que la estructura.
package main
import (
"fmt"
"time"
)
type abc struct {
a, b, c, d int
}
func main() {
var obj abc
t1 := time.Now()
obj.a = 1
obj.b = 2
obj.c = 3
obj.d = 4
t2 := time.Since(t1)
fmt.Println("Struct access time: : ", t2)
a := make([]int, 4)
t3 := time.Now()
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
t4 := time.Since(t3)
fmt.Println("Array access time: : ", t4)
}
Caso 2: Segundo, escribo valores en una matriz y luego en una estructura. Aquí encontré que la estructura es más rápida que la matriz.
package main
import (
"fmt"
"time"
)
type abc struct {
a, b, c, d int
}
func main() {
var obj abc
a := make([]int, 4)
t3 := time.Now()
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
t4 := time.Since(t3)
fmt.Println("Array access time: : ", t4)
t1 := time.Now()
obj.a = 1
obj.b = 2
obj.c = 3
obj.d = 4
t2 := time.Since(t1)
fmt.Println("Struct access time: : ", t2)
}
¿Por qué el rendimiento depende de lo que escribo primero? El que escribo primero parece ser más lento. ¿Por que es esto entonces?
La otra respuesta explicaba la diferencia de tiempo, entremos en estructura vs. rebanada.
Si el compilador puede descubrir en el momento de la compilación que el segmento es lo suficientemente grande, acceder a los elementos del segmento y una estructura generará un código idéntico. Por supuesto, en realidad, a menudo el compilador no sabrá qué tan grande es el segmento y se aplicarán optimizaciones completamente diferentes dependiendo de si está trabajando con una estructura o un segmento, por lo que para medir el rendimiento debe tener en cuenta todo programa y su comportamiento, no solo una operación en particular.