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

go benchmark 基準(zhǔn)測(cè)試詳解

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

一、benchmark的使用

1.一個(gè)簡(jiǎn)單的例子

go mod init test 創(chuàng)建項(xià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 不管是單元測(cè)試還是基準(zhǔn)測(cè)試,測(cè)試函數(shù)都應(yīng)該寫在以_test.go 為結(jié)尾的文件中。

go 單元測(cè)試函數(shù)以Test開頭,函數(shù)參數(shù)為*testing.T

go 基準(zhǔn)測(cè)試函數(shù)以Bench開頭,函數(shù)參數(shù)為*testing.B

2.運(yùn)行用例

如何運(yùn)行測(cè)試用例呢?

運(yùn)行單元測(cè)試:go test -run=xxx,其中xxx為正則表達(dá)式,用來匹配單元測(cè)試函數(shù)的函數(shù)名。

運(yùn)行基準(zhǔn)測(cè)試:go test -bench=xxx,其中xxx為正則表達(dá)式,用來匹配基準(zhǔn)測(cè)試函數(shù)的函數(shù)名。

上述命令只能運(yùn)行當(dāng)前目錄中的測(cè)試用例,如果想運(yùn)行其他目錄的測(cè)試用例呢?

go test -bench=. test/bench/fib  ,指定目標(biāo)包在項(xiàng)目中的絕對(duì)路徑。

go test -bench=. ./fib  , 運(yùn)行當(dāng)前目錄下的子目錄fib中的測(cè)試。

go test -bench=. ./... , 運(yùn)行當(dāng)前目錄下的所有的package中的測(cè)試。

對(duì)-bench=加上正則表達(dá)式:

go test -bench=^BenchmarkFib ./fib

3.benchmark 是如何工作的

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

修改測(cè)試的內(nèi)容,讓運(yùn)行時(shí)間>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數(shù),即cpu核數(shù),可以使用-cpu來指定cpu核數(shù),-cpu=2,3  表示分別使用GOMAXPROCS=2 和GOMAXPROCS=3 進(jìn)行測(cè)試。

可以看到測(cè)試用例運(yùn)行了兩輪,分別以單核和12核,但我們的測(cè)試結(jié)果沒有發(fā)生變化,因?yàn)槲覀兊臏y(cè)試內(nèi)容本身是單核的,與多核無緣。

4.提升準(zhǔn)確度

對(duì)于性能測(cè)試來說,提升測(cè)試精度的一個(gè)重要手段是提升測(cè)試時(shí)間和測(cè)試次數(shù)。我們可以是用-benchtime 和 -count 來達(dá)到目的。

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

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

那么count就是測(cè)試的輪數(shù)了,-count=2 測(cè)試兩輪。

5.內(nèi)存分配情況

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

 因?yàn)閒ib函數(shù)使用的空間全在棧上,不需要進(jìn)行內(nèi)存分配。

下面測(cè)試切片的內(nèi)存分配。創(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)
	}
}

 測(cè)試結(jié)果:

可以看到:

        一次性分配內(nèi)存的切片賦值函數(shù)比多次分配內(nèi)存的切片賦值函數(shù)消耗內(nèi)存更少。

        一次性分配內(nèi)存的切片賦值函數(shù)運(yùn)行時(shí)間更少,因?yàn)閮?nèi)存分配需要耗時(shí)間。

6.測(cè)試不同的輸入

  不同函數(shù)的復(fù)雜度不同,O(1)、O(n)、O(lgn)等,利用 benchmark 驗(yàn)證復(fù)雜度一個(gè)簡(jiǎn)單的方式,是構(gòu)造不同的輸入,對(duì)剛才的generate函數(shù)構(gòu)建不同的輸入可以達(dá)到這個(gè)目的。

  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倍的速度增長(zhǎng),運(yùn)行時(shí)間也按10倍在增長(zhǎng),則函數(shù)的復(fù)雜度是線性的,即O(n).

二、benchmark的注意事項(xiàng)

1.ResetTimer

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

使用sleep模擬耗時(shí)的準(zhǔn)備工作。

fib_test.go 

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

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

使用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)
	}
}

我們將耗時(shí)的準(zhǔn)備工作排除在測(cè)試之外,每次調(diào)用fib(30)花費(fèi) 6ms = 0.006s 

2.StopTimer & StartTimer

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

例:

     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++ {
        //暫停計(jì)時(shí)
		b.StopTimer()
		nums := generateWithCap(10000)
        //繼續(xù)計(jì)時(shí)
		b.StartTimer()
		bubbleSort(nums)
	}
}

顯然我們只測(cè)試到排序的性能,沒有將內(nèi)存分配的時(shí)間花費(fèi)算入結(jié)果。

每次排序需花費(fèi)120ms的時(shí)間。

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

相關(guān)文章

  • Go語言時(shí)間相關(guān)操作合集(超詳細(xì))

    Go語言時(shí)間相關(guān)操作合集(超詳細(xì))

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

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

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

    使用Golang實(shí)現(xiàn)AES加解密的代碼示例

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

    Go基礎(chǔ)教程系列之Go接口使用詳解

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

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

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

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

    這篇文章主要給大家介紹了關(guān)于vscode上搭建go開發(fā)環(huán)境的詳細(xì)完整過程,Go語言或?qū)⒊蔀樾碌闹髁﹂_發(fā)語言,Go是google開發(fā)的一種靜態(tài)強(qiáng)類型、編譯型、并發(fā)型,并具有垃圾回收功能的編程語言,所以我們有必要學(xué)習(xí)并掌握它,需要的朋友可以參考下
    2023-10-10
  • Go語言基礎(chǔ)枚舉的用法及示例詳解

    Go語言基礎(chǔ)枚舉的用法及示例詳解

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

    golang 實(shí)現(xiàn)每隔幾分鐘執(zhí)行一個(gè)函數(shù)

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

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

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

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

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

最新評(píng)論

石狮市| 张家港市| 桐城市| 桓仁| 平阴县| 谷城县| 咸阳市| 阳原县| 峨边| 克东县| 新昌县| 绥棱县| 绩溪县| 同江市| 嫩江县| 吉木萨尔县| 咸宁市| 新沂市| 通榆县| 旬阳县| 平江县| 额尔古纳市| 普陀区| 温泉县| 鄂温| 北海市| 溧水县| 吴忠市| 临沭县| 抚松县| 五指山市| 安溪县| 定结县| 延津县| 延长县| 牡丹江市| 洛川县| 大宁县| 宜丰县| 三穗县| 白河县|