golang 性能測試 (1) 基准性能測試


本文介紹golang 如何做基准性能測試。

編寫完代碼除了跑必要的單元測試外,還需要考慮代碼跑起來的性能如何。性能的衡量其實就是程序運行時候進程的內存分配,CPU消耗情況。

golang 語言在提供了功能測試的基礎上,提供了豐富的性能測試功能。

SHOW CODE

首先,從一個例子來講起。 隨便寫一個簡單的快速排序,然后和系統自帶的排序做一個性能比較。

如下為簡版快排的代碼:

package benchmark

import "sort"

func QSort(data []int) {
	myqsort(data, 0, len(data)-1)
}

func myqsort(data []int, s, e int) {
	if s >= e {
		return
	}

	t := data[s]
	i, j := s, e

	for i < j {
		for ; i < j && data[j] >= t; j-- { }
		for ; i < j && data[i] < t; i++ { }
		if i < j { break }

		data[i], data[j] = data[j], data[i]
		i++
		j--
	}

	data[i] = t
	myqsort(data, s, i-1)
	myqsort(data, i+1, e)
}

然后編寫一個測試的test。

package benchmark

import "testing"
import "math/rand"
import "time"
import "sort"

var ints []int

// 長度為 1w 的數據使用系統自帶排序
func BenchmarkSort10k(t *testing.B) {
	slice := ints[0:10000]
	t.ResetTimer()   // 只考慮下面代碼的運行事件,所以重置計時器
	for i := 0; i < t.N; i++ {
		sort.Ints(slice)
	}
}

// 長度為 100 的數據使用系統自帶排序
func BenchmarkSort100(t *testing.B) {
	slice := ints[0:100]
	t.ResetTimer()
	for i := 0; i < t.N; i++ {
		sort.Ints(slice)
	}
}

// 長度為 1w 的數據使用上述代碼排序
func BenchmarkQsort10k(t *testing.B) {
	slice := ints[0:10000]
	t.ResetTimer()
	for i := 0; i < t.N; i++ {
		QSort(slice)
	}
}

// 長度為 100 的數據使用上述代碼排序
func BenchmarkQsort100(t *testing.B) {
	slice := ints[0:100]
	t.ResetTimer()
	for i := 0; i < t.N; i++ {
		QSort(slice)
	}
}

// 數據初始化,為了保證每次數據都是一致的。
func TestMain(m *testing.M) {
	rand.Seed(time.Now().Unix())
	ints = make([]int, 10000)

	for i := 0; i < 10000; i++ {
		ints[i] = rand.Int()
	}

	m.Run()
}

運行命令 :

# go test -cover -count 3  -benchmem  -bench=.

運行結果如下圖:

基准測試,默認將每個方法執行1s中,然后展示執行的次數,每一次執行的耗時, 上述還展示了內存每次分配的大小,以及每次benchmark分配的次數。上述的命令行指定了運行次數為3次,顯示代碼覆蓋率和內存分配情況。

從基准測試的結果可以分析出:對於1w數據量的排序,自帶的排序比我的排序算法要快20倍左右;100數據量的排序,手擼的排序略勝一籌。
從內存分析來講,系統自帶的會使用4B的數據,而我的算法無內存分配。

INTRODUCE BENCHMARK

引入golang 提供的 testing 包,寫需要的基准測試的方法(方法名必須以Benchmark開頭, 參數必須為 *testing.B)。

若需要做一些數據初始化的工作,可以如上寫一個TestMain 方法,將數據初始化的工作在這里完成。

除了這些,可以看*testing.B, *testing.M 的相關方法即可。

最后,只要運行官方提供的 go test -bench=. 命令,即可開始跑基准測試。 當然,還有其他選項可以滿足我們多樣的需求。
例如:

  • -cpu 1,2,4 指定運行的cpu 格式
  • -count n 指定運行的次數
  • -benchtime 每一條測試執行的時間 (默認是1s)
  • -bench 指定執行bench的方法, . 是全部
  • -benchmem 顯示內存分配情況

其他參數可以通過 go help testflag 查看

WHY SO SLOW

  1. 我這里選取的是第一個數作為中位數,數據越大越可能出現傾斜,排序慢的概率也大。
  2. 正常的排序包中,都會在對小於等於12 個數的數組做排序時使用希爾排序,速度也有很大提升。

除了簡單的做性能測試外,golang 還自帶了性能分析的工具,我們可以快速找出代碼中的內存分配、cpu消耗的核心區,幫助我們解決服務的性能問題。下篇文章將做詳細了解。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM