最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

go benchmark 基準測試詳解

 更新時間:2023年03月31日 11:25:26   作者:qq_42170897  
這篇文章主要介紹了go benchmark 基準測試詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

一、benchmark的使用

1.一個簡單的例子

go mod init test 創(chuàng)建項目test,創(chuàng)建目錄bench/fib

創(chuàng)建fib.go

package fib
 
func fib(n int) int {
	if n == 0 || n == 1 {
		return n
	}
	return fib(n-1) + fib(n-2)
}

創(chuàng)建fib_test.go

package fib
 
import (
	"testing"
)
 
func BenchmarkFib(b *testing.B) {
	for i := 0; i < b.N; i++ {
		fib(30)
	}
}

go 不管是單元測試還是基準測試,測試函數都應該寫在以_test.go 為結尾的文件中。

go 單元測試函數以Test開頭,函數參數為*testing.T

go 基準測試函數以Bench開頭,函數參數為*testing.B

2.運行用例

如何運行測試用例呢?

運行單元測試:go test -run=xxx,其中xxx為正則表達式,用來匹配單元測試函數的函數名。

運行基準測試:go test -bench=xxx,其中xxx為正則表達式,用來匹配基準測試函數的函數名。

上述命令只能運行當前目錄中的測試用例,如果想運行其他目錄的測試用例呢?

go test -bench=. test/bench/fib  ,指定目標包在項目中的絕對路徑。

go test -bench=. ./fib  , 運行當前目錄下的子目錄fib中的測試。

go test -bench=. ./... , 運行當前目錄下的所有的package中的測試。

對-bench=加上正則表達式:

go test -bench=^BenchmarkFib ./fib

3.benchmark 是如何工作的

benchmark用例的參數為b testing.B, b.N 表示要測試的內容運行的次數,這個次數對于每個用例都不同。那么這個次數變化規(guī)律是什么呢?b.N從1開始,如果內容在1s內運行結束,那么b.N會增加,測試會再次執(zhí)行。b.N 的值大概以 1, 2, 3, 5, 10, 20, 30, 50, 100 這樣的序列遞增,越到后面,增加得越快。

修改測試的內容,讓運行時間>1s

func BenchmarkFib(b *testing.B) {
	for i := 0; i < b.N; i++ {
		time.Sleep(time.Second)
		fib(30)
	}
}

 可以看到,只執(zhí)行了1次。

benchmarkFib-12 的-12的意思是 GOMAXPROCS數,即cpu核數,可以使用-cpu來指定cpu核數,-cpu=2,3  表示分別使用GOMAXPROCS=2 和GOMAXPROCS=3 進行測試。

可以看到測試用例運行了兩輪,分別以單核和12核,但我們的測試結果沒有發(fā)生變化,因為我們的測試內容本身是單核的,與多核無緣。

4.提升準確度

對于性能測試來說,提升測試精度的一個重要手段是提升測試時間和測試次數。我們可以是用-benchtime 和 -count 來達到目的。

benchmark 默認的benchtime是1s,我們指定2s,可以看到執(zhí)行次數也提升了約1倍。

我們還能直接指定b.N ,即 -benchtime=30x 表示30次

那么count就是測試的輪數了,-count=2 測試兩輪。

5.內存分配情況

前面的測試結果中,只能看見執(zhí)行的次數和一次執(zhí)行的時間,沒有任何與內存相關的信息。加入 -benchmem 就可以看到。

 因為fib函數使用的空間全在棧上,不需要進行內存分配。

下面測試切片的內存分配。創(chuàng)建目錄 bench/cap

cap.go

// 一次性分配空間
func generateWithCap(n int) []int {
	rand.Seed(time.Now().UnixNano())
	nums := make([]int, 0, n)
	for i := 0; i < n; i++ {
		nums = append(nums, rand.Int())
	}
	return nums
}
 
// 多次分配空間
func generate(n int) []int {
	rand.Seed(time.Now().UnixNano())
	nums := make([]int, 0)
	for i := 0; i < n; i++ {
		nums = append(nums, rand.Int())
	}
	return nums
}

cap_test.go

package cap
 
import "testing"
 
func BenchmarkGenerateWithCap(b *testing.B) {
	for n := 0; n < b.N; n++ {
		generateWithCap(1000000)
	}
}
 
func BenchmarkGenerate(b *testing.B) {
	for n := 0; n < b.N; n++ {
		generate(1000000)
	}
}

 測試結果:

可以看到:

        一次性分配內存的切片賦值函數比多次分配內存的切片賦值函數消耗內存更少。

        一次性分配內存的切片賦值函數運行時間更少,因為內存分配需要耗時間。

6.測試不同的輸入

  不同函數的復雜度不同,O(1)、O(n)、O(lgn)等,利用 benchmark 驗證復雜度一個簡單的方式,是構造不同的輸入,對剛才的generate函數構建不同的輸入可以達到這個目的。

  cap_test.go

func benchmarkGenerate(n int, b *testing.B) {
	for i := 0; i < b.N; i++ {
		generate(n)
	}
}
 
func BenchmarkGenerate1000(b *testing.B)    { benchmarkGenerate(1000, b) }
func BenchmarkGenerate10000(b *testing.B)   { benchmarkGenerate(10000, b) }
func BenchmarkGenerate100000(b *testing.B)  { benchmarkGenerate(100000, b) }
func BenchmarkGenerate1000000(b *testing.B) { benchmarkGenerate(1000000, b) }

隨著輸入按10倍的速度增長,運行時間也按10倍在增長,則函數的復雜度是線性的,即O(n).

二、benchmark的注意事項

1.ResetTimer

如果在正式執(zhí)行測試前需要進行準備工作,那么在準備工作完成后,可以使用b.ResetTimer() 函數來重置計數器。

使用sleep模擬耗時的準備工作。

fib_test.go 

func BenchmarkFib(b *testing.B) {
	time.Sleep(time.Second)
	for i := 0; i < b.N; i++ {
		fib(30)
	}
}

每次執(zhí)行fib(30)高達1s多,顯然不對。

使用b.ResetTimer()

 fib_test.go

func BenchmarkFib(b *testing.B) {
	time.Sleep(time.Second)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		fib(30)
	}
}

我們將耗時的準備工作排除在測試之外,每次調用fib(30)花費 6ms = 0.006s 

2.StopTimer & StartTimer

如果在每一次函數前后都需要準備工作和清理工作,那么就需要StopTimer + StartTimer 函數了。

例:

     sort_test.go

// 一次性分配空間
func generateWithCap(n int) []int {
	rand.Seed(time.Now().UnixNano())
	nums := make([]int, 0, n)
	for i := 0; i < n; i++ {
		nums = append(nums, rand.Int())
	}
	return nums
}
 
 
//冒泡排序
func bubbleSort(nums []int) {
	for i := 0; i < len(nums); i++ {
		for j := 1; j < len(nums)-i; j++ {
			if nums[j] < nums[j-1] {
				nums[j], nums[j-1] = nums[j-1], nums[j]
			}
		}
	}
}
 
func BenchmarkBubbleSort(b *testing.B) {
	for n := 0; n < b.N; n++ {
        //暫停計時
		b.StopTimer()
		nums := generateWithCap(10000)
        //繼續(xù)計時
		b.StartTimer()
		bubbleSort(nums)
	}
}

顯然我們只測試到排序的性能,沒有將內存分配的時間花費算入結果。

每次排序需花費120ms的時間。

到此這篇關于go benchmark 基準測試的文章就介紹到這了,更多相關go 基準測試內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Go語言時間相關操作合集(超詳細)

    Go語言時間相關操作合集(超詳細)

    在開發(fā)應用程序的過程中,經常需要記錄某些操作的時間或者格式化時間戳,因此大部分編程語言都會有操作時間的庫,Go語言當然也不例外,本文我們就一起來學習一下time包的使用
    2023-08-08
  • 使用VSCODE配置GO語言開發(fā)環(huán)境的完整步驟

    使用VSCODE配置GO語言開發(fā)環(huán)境的完整步驟

    Go語言是采用UTF8編碼的,理論上使用任何文本編輯器都能做Go語言開發(fā),大家可以根據自己的喜好自行選擇,下面這篇文章主要給大家介紹了關于使用VSCODE配置GO語言開發(fā)環(huán)境的完整步驟,需要的朋友可以參考下
    2022-11-11
  • 使用Golang實現AES加解密的代碼示例

    使用Golang實現AES加解密的代碼示例

    在現代的數據安全中,加密和解密是極其重要的一環(huán),其中,高級加密標準(AES)是最廣泛使用的加密算法之一,本文將介紹如何使用Golang來實現AES加密和解密,需要的朋友可以參考下
    2024-04-04
  • Go基礎教程系列之Go接口使用詳解

    Go基礎教程系列之Go接口使用詳解

    這篇文章主要介紹了Go基礎教程系列之Go接口使用詳解,需要的朋友可以參考下
    2022-04-04
  • 使用docker構建golang線上部署環(huán)境的步驟詳解

    使用docker構建golang線上部署環(huán)境的步驟詳解

    這篇文章主要介紹了使用docker構建golang線上部署環(huán)境的步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2017-11-11
  • vscode上搭建go開發(fā)環(huán)境詳細完整過程

    vscode上搭建go開發(fā)環(huán)境詳細完整過程

    這篇文章主要給大家介紹了關于vscode上搭建go開發(fā)環(huán)境的詳細完整過程,Go語言或將成為新的主力開發(fā)語言,Go是google開發(fā)的一種靜態(tài)強類型、編譯型、并發(fā)型,并具有垃圾回收功能的編程語言,所以我們有必要學習并掌握它,需要的朋友可以參考下
    2023-10-10
  • Go語言基礎枚舉的用法及示例詳解

    Go語言基礎枚舉的用法及示例詳解

    這篇文章主要為大家介紹了Go語言基礎枚舉的用法及示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2021-11-11
  • golang 實現每隔幾分鐘執(zhí)行一個函數

    golang 實現每隔幾分鐘執(zhí)行一個函數

    這篇文章主要介紹了golang 實現每隔幾分鐘執(zhí)行一個函數,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • 基于Golang 高并發(fā)問題的解決方案

    基于Golang 高并發(fā)問題的解決方案

    這篇文章主要介紹了Golang 高并發(fā)問題的解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • Golang中json和jsoniter的區(qū)別使用示例

    Golang中json和jsoniter的區(qū)別使用示例

    這篇文章主要介紹了Golang中json和jsoniter的區(qū)別使用示例,本文給大家分享兩種區(qū)別,結合示例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2023-12-12

最新評論

民县| 肥城市| 平塘县| 武威市| 鄱阳县| 称多县| 临江市| 广饶县| 从江县| 卢龙县| 金平| 汝南县| 财经| 乌拉特中旗| 大田县| 望奎县| 澜沧| 江华| 甘南县| 唐河县| 新河县| 达拉特旗| 曲麻莱县| 隆子县| 石狮市| 巴青县| 五河县| 金山区| 焉耆| 增城市| 准格尔旗| 铅山县| 蒲江县| 恩平市| 三都| 苍南县| 凌源市| 米易县| 海淀区| 昌宁县| 舞阳县|