🔥 PRUEBAS, BENCHMARK DE PRUEBAS

¿Qué es el benchmark?

Realizar pruebas de rendimiento en programas en Go es esencial para conocer la eficiencia real de nuestro código y detectar posibles mejoras. Una de las formas más recomendadas de hacerlo es utilizar el paquete testing, que proporciona un completo framework en Go que permite ejecutar pruebas de benchmarking de manera sencilla y automatizada.

Por ejemplo, si queremos saber cómo medir el rendimiento de funciones en Go al construir un string dentro de un ciclo, podemos comparar diferentes técnicas. Se ha comprobado que el uso de buffers suele ser más eficiente que la concatenación directa con += o la unión de arreglos de strings. Para verificarlo, se pueden crear tres funciones, cada una con un enfoque distinto.

A continuación, se muestra el paquete longstring en el archivo longstring.go:

package longstring

import (
    "bytes"
    "strings"
)

func MedianteConcatenacion(longitud int) string {
    var s string
    for i := 0; i < longitud; i++ {
        s += "texto"
    }
    return s
}

func MedianteArreglo(longitud int) string {
    s := []string{}
    for i := 0; i < longitud; i++ {
        s = append(s, "texto")
    }
    return strings.Join(s, "")
}

func MedianteBuffer(longitud int) string {
    var buffer bytes.Buffer
    for i := 0; i < longitud; i++ {
        buffer.WriteString("texto")
    }
    return buffer.String()
}

En este ejemplo, las tres funciones cumplen el mismo objetivo: construir un string de salida. La cantidad de iteraciones del ciclo depende del parámetro longitud.

  • MedianteConcatenacion
  • MedianteArreglo
  • MedianteBuffer

Para aprender cómo hacer pruebas de rendimiento en Go, es necesario crear funciones de benchmark. Estas funciones, a diferencia de los tests tradicionales, llevan el prefijo Benchmark y reciben como argumento un puntero a testing.B. Este parámetro contiene el valor N, que indica cuántas veces se repetirá el ciclo, ajustándose automáticamente según lo requiera el framework. Así, se puede evaluar el rendimiento de cada método de manera objetiva.

package longstring

import "testing"

func BenchmarkMedianteConcatenacion(b *testing.B) {
    for i := 0; i < b.N; i++ {
        MedianteConcatenacion(100)
    }
}

func BenchmarkMedianteArreglo(b *testing.B) {
    for i := 0; i < b.N; i++ {
        MedianteArreglo(100)
    }
}

func BenchmarkMedianteBuffer(b *testing.B) {
    for i := 0; i < b.N; i++ {
        MedianteBuffer(100)
    }
}

Al ejecutar los benchmarks, se obtienen resultados detallados que permiten interpretar resultados de benchmark en Go y comparar el desempeño de cada función.

go test -bench=.
goos: darwin
goarch: amd64
pkg: .../benchmark
BenchmarkMedianteConcatenacion-8      200000          7916 ns/op
BenchmarkMedianteArreglo-8            500000          2464 ns/op
BenchmarkMedianteBuffer-8            1000000          1429 ns/op
PASS
ok      .../benchmark    4.378s

En este caso, los resultados muestran que la función BenchmarkMedianteBuffer es la más eficiente, lo que confirma la importancia de optimizar el rendimiento de funciones en Go mediante el uso de benchmarks.


Conclusión

El uso de benchmarks en Go es una herramienta esencial para cualquier desarrollador que busque mejorar la eficiencia de sus programas. Gracias al paquete testing, es posible comparar distintas implementaciones y tomar decisiones informadas sobre cuál es la más adecuada para cada caso. Aplicar mejores prácticas para benchmarks en Go permite identificar rápidamente las áreas de mejora y optimizar el rendimiento de las funciones críticas. Además, saber cómo hacer pruebas de rendimiento en Go y interpretar resultados de benchmark en Go facilita el desarrollo de aplicaciones más rápidas y robustas. En definitiva, dominar estas técnicas contribuye significativamente a la calidad y competitividad del software desarrollado en Golang.


Cuestionario de repaso

  1. ¿Para qué sirve realizar benchmarks en Go?
  2. ¿Qué diferencia hay entre una función de test y una de benchmark en Go?
  3. ¿Qué parámetro especial reciben las funciones de benchmark y cuál es su propósito?
  4. ¿Por qué es importante comparar diferentes métodos de construcción de strings en Go?
  5. ¿Cómo se interpreta el resultado de un benchmark en la salida de la terminal?
  6. ¿Cuál de los métodos presentados resultó ser el más eficiente según el benchmark?

Otros Artículos