Go語言之基準測試

2021-09-20 20:02:34 字數 3255 閱讀 7894

什麼是基準測試

基準測試,是一種測試**效能的方法,比如你有多種不同的方案,都可以解決問題,那麼到底是那種方案效能更好呢?這時候基準測試就派上用場了。

基準測試主要是通過測試cpu和記憶體的效率問題,來評估被測試**的效能,進而找到更好的解決方案。比如鏈結池的數量不是越多越好,那麼哪個值才是最優值呢,這就需要配合基準測試不斷調優了。

如何編寫基準測試

基準測試**的編寫和單元測試非常相似,它也有一定的規則,我們先看乙個示例。

itoa_test.go

func 

benchmarksprintf(b

*testing.b

)}

這是乙個基準測試的例子,從中我們可以看出以下規則:

下面我們執行下基準測試,看看效果。

hello go test

-bench=.-

run=

none

benchmarksprintf-8

20000000

117ns/op

pass

ok      flysnow

.org

/hello      

2.474s

執行基準測試也要使用

go test

命令,不過我們要加上

-bench=

標記,它接受乙個表示式作為引數,匹配基準測試的函式,

.表示執行所有基準測試。

因為預設情況下

go test

會執行單元測試,為了防止單元測試的輸出影響我們檢視基準測試的結果,可以使用

-run=

匹配乙個從來沒有的單元測試方法,過濾掉單元測試的輸出,我們這裡使用

none

,因為我們基本上不會建立這個名字的單元測試方法。

下面著重解釋下說出的結果,看到函式後面的

-8了嗎?這個表示執行時對應的gomaxprocs的值。接著的

20000000

表示執行for迴圈的次數,也就是呼叫被測試**的次數,最後的

117 ns/op

表示每次需要話費 117 納秒。

以上是測試時間預設是 1 秒,也就是 1 秒的時間,呼叫兩千萬次,每次呼叫花費 117 納秒。如果想讓測試執行的時間更長,可以通過

-benchtime

指定,比如 3 秒。

hello go test

-bench=.-

benchtime=3s

-run

=none

benchmarksprintf-8

50000000

109ns/op

pass

ok      flysnow

.org

/hello      

5.628s

可以發現,我們加長了測試時間,測試的次數變多了,但是最終的效能結果:每次執行的時間,並沒有太大變化。一般來說這個值最好不要超過3秒,意義不大。

效能對比

上面那個基準測試的例子,其實是乙個int型別轉為string型別的例子,標準庫里還有幾種方法,我們看下哪種效能更加。

func 

benchmarksprintf(b

*testing.b

)}func

benchmarkformat(b

*testing.b

)}func

benchmarkitoa(b

*testing.b

)}

執行基準測試,看看結果:

hello go test

-bench=.-

run=

none              

benchmarksprintf-8

20000000

117ns/op

benchmarkformat-8

50000000

33.3ns/

opbenchmarkitoa-8

50000000

34.9ns/

oppass

ok      flysnow

.org

/hello      

5.951s

從結果上看

strconv.formatint

函式是最快的,其次是

strconv.itoa

,然後是

fmt.sprintf

最慢,前兩個函式效能達到了最後乙個的 3 倍多。那麼最後乙個為什麼這麼慢的,我們再通過

-benchmem

找到根本原因。

hello go test

-bench=.-

benchmem

-run

=none

benchmarksprintf-8

20000000

110ns

/op      16b

/op      

2allocs/op

benchmarkformat-8

50000000

31.0ns/

op     2b

/op       

1allocs/op

benchmarkitoa-8

50000000

33.1ns/

op     2b

/op      

1allocs/op

pass

ok      flysnow

.org

/hello      

5.610s

-benchmem

可以提供每次操作分配記憶體的次數,以及每次操作分配的位元組數。從結果我們可以看到,效能高的兩個函式,每次操作都是進行 1 次記憶體分配,而最慢的那個要分配 2 次;效能高的每次操作分配 2 個位元組記憶體,而慢的那個函式每次需要分配 16 位元組的記憶體。從這個資料我們就知道它為什麼這麼慢了,記憶體分配都占用都太高。

在**開發中,對於我們要求效能的地方,編寫基準測試非常重要,這有助於我們開發出效能更好的**。不過效能、可用性、復用性等也要有乙個相對的取捨,不能為了追求效能而過度優化。

Go語言之GO 語言常量

相對於變數,常量是恆定不變的值,多用於定義程式執行期間不會改變的那些值。常量的宣告和變數宣告非常類似,只是把var換成了const,常量在定義的時候必須賦值。const pi 3.1415 const e 2.7182宣告了pi和e這兩個常量之後,在整個程式執行期間它們的值都不能再發生變化了。多個常...

Go語言之Go語言網路程式設計

go語言的 net 包中有乙個 tcpconn 型別,可以用來建立 tcp 客戶端和 tcp 伺服器端間的通訊通道,tcpconn 型別裡有兩個主要的函式 func c tcpconn write b byte n int,err os.error func c tcpconn read b byt...

Go語言之Go 語言迴圈語句

go 語言提供了以下幾種型別迴圈處理語句 迴圈型別 描述for 迴圈 重複執行語句塊 迴圈巢狀 在 for 迴圈中巢狀乙個或多個 for 迴圈 迴圈控制語句可以控制迴圈體內語句的執行過程。go 語言支援以下幾種迴圈控制語句 控制語句 描述break 語句 經常用於中斷當前 for 迴圈或跳出 swi...