Golang Benchmark HTTP Server 10 Juta Kali dan Baca Profiling

Cecep Aprilianto
3 min readJul 7, 2024

--

Menulis test benchmark di Golang untuk HTTP server cukup mudah, kalian perlu menggunakan package testing built-in bawaan Golang itu sendiri, yang menyediakan fungsionalitas untuk membuat benchmark. Di bawah ini adalah contoh sederhana cara membuat tes benchmark Go untuk HTTP server.

bench capture

Example HTTP Server

Pertama, buat HTTP server sederhana untuk di test pada file main.go. Buat handler HTTP dasar yang merespons dengan “Hello, World!”.

package main

import (
"fmt"
"log"
"net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
_, err := fmt.Fprintf(w, "Hello, World!")
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}

func main() {
http.HandleFunc("/", helloHandler)
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatalf("Could not start server: %s\n", err)
}
}

Benchmark Test

Selanjutnya, tulis tes benchmark untuk mengukur performa helloHandler. Fungsi benchmark harus dimulai dengan kata ‘Benchmark’ dan parameter *testing.B

Buat file baru bernama `main_test.go`

package main

import (
"net/http"
"net/http/httptest"
"testing"
)

// BenchmarkHelloHandler benchmarks the helloHandler function.
func BenchmarkHelloHandler(b *testing.B) {
// Create a new HTTP request for the benchmark.
req, err := http.NewRequest("GET", "/", nil)
if err != nil {
b.Fatal(err)
}

// Create a ResponseRecorder to record the response.
rr := httptest.NewRecorder()

// Get the handler function.
handler := http.HandlerFunc(helloHandler)

// Run the benchmark.
for i := 0; i < b.N; i++ {
// Serve the HTTP request.
handler.ServeHTTP(rr, req)

// Check the status code to make sure everything is OK.
if status := rr.Code; status != http.StatusOK {
b.Errorf("handler returned wrong status code: got %v want %v",
status, http.StatusOK)
}

// Check the response body to make sure it's what we expect.
expected := "Hello, World!"
if rr.Body.String() != expected {
b.Errorf("handler returned unexpected body: got %v want %v",
rr.Body.String(), expected)
}

// Reset the ResponseRecorder for the next iteration.
rr.Body.Reset()
}
}

Running the Benchmark

Untuk menjalankan test benchmark, gunakan perintah go test dengan flag -bench seperti berikut:

go test . -bench=BenchmarkHelloHandler -benchtime=10000000x -v -benchmem -cpuprofile=cpu.out -run="^$"

maka hasilnya seperti gambar berikut

go test benchmark

Explanation

  • go test: Ini adalah perintah Go untuk menjalankan tes.
  • (.) dot: Ini menentukan current direktori sebagai test yang akan diuji.
  • -bench=BenchmarkHelloHandler: Flag ini menentukan benchmark mana yang akan dijalankan. Dalam test ini hanya menjalankan fungsi benchmark BenchmarkHelloHandler. Jika kalian ingin menjalankan semua benchmark, maka dapat menggunakan “-bench=.”
  • -benchtime=10000000x: Ini menentukan jumlah waktu untuk menjalankan benchmark. 10000000x berarti benchmark harus menjalankan 10 juta kali iterasi. Contoh lainnya dari -benchtime yaitu durasi (misal, -benchtime=1s), tapi saat kalian menambahkan x ke sebuah angka, benchmark akan dijalankan berkali-kali.
  • -v: Flag ini mengaktifkan verbose, artinya hasil pengujian akan menyertakan informasi detail tentang pengujian yang dijalankan.
  • -benchmem: Flag ini mengaktifkan alokasi memori untuk benchmark. Ini akan menunjukkan jumlah alokasi dan byte yang dialokasikan per operasi.
  • -cpuprofile=cpu.out: Flag ini membuat profil CPU ke file yang ditentukan (misalnya: cpu.out). File ini nantinya dapat dianalisis untuk menemukan hambatan kinerja.
  • -run=”^$”: Flag ini menentukan pengujian mana yang akan dijalankan. Regex ^$ memastikan bahwa hanya benchmark yang dijalankan.

Dengan mengikuti langkah-langkah ini, kalian memastikan bahwa server http dan test benchmark kalian kuat dan menangani kesalahan dengan tepat.

Read Profiling

Salah satu cara baca profiling hasil test benchmark yaitu dengan upload file nya melalui situs online https://www.speedscope.app/

Profiling berguna untuk memahami bagian kode atau sistem mana yang paling banyak mengonsumsi resource (CPU, memori, I/O disk, dll.) membantu mengoptimalkan kerja sebuah aplikasi. Jadi, kita bisa mencari bottleneck didalam kode kita tanpa membuang waktu improvement yang tidak jelas.

Berikut ini hasil dari profiling speedscope. Bisa berdasarkan waktu ataupun bentuk table:

speedscope result time order
speedscope result table

--

--

Cecep Aprilianto
Cecep Aprilianto

Written by Cecep Aprilianto

Web and Backend Developer at Internet

No responses yet