這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
在用Go做一個SQL產生的工具,對他的字串拼接的效能表示好奇,在google搜了半天,好像認真的老外都沒有這方面的結果,所以自己動手弄一個吧!
先上結論
| |
第1次 |
第2次 |
第3次 |
第4次 |
第5次 |
| 2參數/100萬次 |
|
|
|
|
|
| fmt.Sprintf |
0.5550317 |
0.5800332 |
0.5800332 |
0.5090291 |
0.5160295 |
| bytes.NewBuffer |
0.9450541 |
1.0010573 |
0.9430539 |
0.9500544 |
0.9600549 |
| + |
0.1460083 |
0.1700097 |
0.1470085 |
0.1450083 |
0.1560089 |
| strings.Join |
0.279016 |
0.3030173 |
0.2820161 |
0.2760158 |
0.3080176 |
| 4參數/100萬次 |
|
|
|
|
|
| fmt.Sprintf |
1.0260587 |
0.944054 |
1.0270587 |
0.944054 |
0.9530545 |
| bytes.NewBuffer |
1.4470828 |
1.3770788 |
1.3970799 |
1.5100864 |
1.4890852 |
| + |
0.2920167 |
0.2580147 |
0.2630151 |
0.2880164 |
0.2860163 |
| strings.Join |
0.4670267 |
0.4560261 |
0.4700269 |
0.4620265 |
0.4630265 |
| 6參數/100萬次 |
|
|
|
|
|
| fmt.Sprintf |
1.4090806 |
1.3880794 |
1.4110808 |
1.4290817 |
1.3900795 |
| bytes.NewBuffer |
1.5800904 |
1.5240871 |
1.5440883 |
1.5990915 |
1.57209 |
| + |
0.4000229 |
0.4030231 |
0.3940225 |
0.4110235 |
0.4080233 |
| strings.Join |
0.5630322 |
0.6270358 |
0.6280359 |
0.5840334 |
0.6340363 |
|
哦,是的,字串+是最快的,當然這裡只是一個簡單測試的結果,具體情況還是選擇最符合使用情境的方法吧。
如果有新結果,會更新到這邊:http://git.oschina.net/janpoem/go-benchmarks
測試代碼
package mainimport ( "git.oschina.net/janpoem/go-agi")import ( "fmt" "math/rand" "strconv" "bytes" "strings")func randStr() (string) { return strconv.FormatInt(rand.Int63(), 36)}var sp_str1 = randStr()var sp_str2 = randStr()var sp_str3 = randStr()var sp_str4 = randStr()var sp_str5 = randStr()var sp_str6 = randStr()func test_2_args() { max := 1000000 dur1 := agi.TimesTest(max, func() { fmt.Sprintf("SELECT %s FROM %s", sp_str1, sp_str2) }) dur2 := agi.TimesTest(max, func() { bf := bytes.NewBufferString("SELECT") bf.WriteString(" ") bf.WriteString(sp_str1) bf.WriteString(" ") bf.WriteString("FROM") bf.WriteString(sp_str2) }) dur3 := agi.TimesTest(max, func() { bf := "SELECT " + sp_str1 + " FROM " + sp_str2 if len(bf) > 0 { } }) dur4 := agi.TimesTest(max, func() { bf := strings.Join([]string { "SELECT", sp_str1, "FROM", sp_str2 }, "") if len(bf) > 0 { } }) fmt.Println(dur1.Seconds()) fmt.Println(dur2.Seconds()) fmt.Println(dur3.Seconds()) fmt.Println(dur4.Seconds())}func test_4_args() { max := 1000000 dur1 := agi.TimesTest(max, func() { fmt.Sprintf("SELECT %s FROM %s WHERE %s ORDER BY %s", sp_str1, sp_str2, sp_str3, sp_str4) }) dur2 := agi.TimesTest(max, func() { bf := bytes.NewBufferString("SELECT ") bf.WriteString(sp_str1) bf.WriteString(" ") bf.WriteString("FROM ") bf.WriteString(sp_str2) bf.WriteString(" ") bf.WriteString("WHERE ") bf.WriteString(sp_str3) bf.WriteString(" ") bf.WriteString("ORDER BY ") bf.WriteString(sp_str4) }) dur3 := agi.TimesTest(max, func() { bf := "SELECT " + sp_str1 + " FROM " + sp_str2 + " WHERE " + sp_str3 + " ORDER BY " + sp_str4 if len(bf) > 0 { } }) dur4 := agi.TimesTest(max, func() { bf := strings.Join([]string { "SELECT", sp_str1, "FROM", sp_str2, "WHERE", sp_str3, "ORDER BY", sp_str4 }, "") if len(bf) > 0 { } }) fmt.Println(dur1.Seconds()) fmt.Println(dur2.Seconds()) fmt.Println(dur3.Seconds()) fmt.Println(dur4.Seconds())}func test_6_args() { max := 1000000 dur1 := agi.TimesTest(max, func() { fmt.Sprintf("SELECT %s FROM %s WHERE %s ORDER BY %s GROUP BY %s LIMIT %s", sp_str1, sp_str2, sp_str3, sp_str4, sp_str5, sp_str6) }) dur2 := agi.TimesTest(max, func() { bf := bytes.NewBufferString("SELECT ") bf.WriteString(sp_str1) bf.WriteString(" ") bf.WriteString("FROM ") bf.WriteString(sp_str2) bf.WriteString(" ") bf.WriteString("WHERE ") bf.WriteString(sp_str3) bf.WriteString(" ") bf.WriteString("ORDER BY ") bf.WriteString(sp_str4) bf.WriteString(" ") bf.WriteString("GROUP BY ") bf.WriteString(sp_str5) bf.WriteString(" ") bf.WriteString("LIMIT ") bf.WriteString(sp_str6) }) dur3 := agi.TimesTest(max, func() { bf := "SELECT " + sp_str1 + " FROM " + sp_str2 + " WHERE " + sp_str3 + " ORDER BY " + sp_str4 + " GROUP BY " + sp_str5 + " LIMIT " + sp_str6 if len(bf) > 0 { } }) dur4 := agi.TimesTest(max, func() { bf := strings.Join([]string { "SELECT", sp_str1, "FROM", sp_str2, "WHERE", sp_str3, "ORDER BY", sp_str4, "GROUP BY", sp_str5, "LIMIT", sp_str6, }, "") if len(bf) > 0 { } }) fmt.Println(dur1.Seconds()) fmt.Println(dur2.Seconds()) fmt.Println(dur3.Seconds()) fmt.Println(dur4.Seconds())}func main() {// test_2_args()// test_4_args()// test_6_args()}
具體代碼在這裡:http://git.oschina.net/janpoem/go-benchmarks/blob/master/str_concat.go
TimesTest,調用的是這個:benchmark.go,他的功能就是根據你傳入的次數,執行指定的匿名函數多少次。起初對執行匿名函數的效能有些擔心,不過比較了一下裸代碼和匿名函數的執行時間,相差的並不多,就忽略吧。
這次測試只是對執行時間的一個測試,不包含CPU和記憶體情況監控。
呃,額外的說, @紅薯 部落格的markdown編輯器是不是太奇葩了,table、代碼,什麼格式都不支援,太難用了。