什麼是基準測試
基準測試,是一種測試**效能的方法,比如你有多種不同的方案,都可以解決問題,那麼到底是那種方案效能更好呢?這時候基準測試就派上用場了。
基準測試主要是通過測試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...