mymysql和go-mysql-driver是兩個現在都很流行的go的mysql驅動,這篇文章目的是要将這兩個驅動進行一下比較
兩個mysql驅動的下載下傳位址:
<a href="https://github.com/ziutek/mymysql">https://github.com/ziutek/mymysql</a>
<a href="http://code.google.com/p/go-mysql-driver/">http://code.google.com/p/go-mysql-driver/</a>
在mysql建表和初始化資料(db是test)
1
2
3
4
5
6
7
8
9
10
11
12
13
<code>drop table</code><code>if</code> <code>exists admin;</code>
<code>create table `admin` (</code>
<code> </code><code>`adminid` int(10) unsigned not null auto_increment,</code>
<code> </code><code>`username` varchar(20) not null default</code><code>''</code> <code>comment</code><code>'背景使用者名'</code><code>,</code>
<code> </code><code>`password` char(32) not null default</code><code>''</code> <code>comment</code><code>'密碼,md5存'</code><code>,</code>
<code> </code><code>primary key(`adminid`)</code>
<code>)</code>
<code>comment=</code><code>'背景使用者資訊表'</code>
<code>collate=</code><code>'utf8_general_ci'</code>
<code>engine=innodb;</code>
<code>insert into admin set adminid=1, username=</code><code>'admin'</code><code>, password=</code><code>'21232f297a57a5a743894a0e4a801fc3'</code><code>;</code>

已經将gomysqldriver和mymysql的代碼放到github上了,有興趣的去裡面看看。
<a href="https://github.com/jianfengye/myworks/tree/master/gomysqltest">https://github.com/jianfengye/myworks/tree/master/gomysqltest</a>
代碼裡面注意的幾點就是我們測試了get,insert,update三個操作,并且insert的時候不指定主鍵,讓其自增,innodb的表,這樣讓mysql處理插入操作盡可能快。
mymysql的表現:
go-mysql-driver的表現:
benchmark的測試用例名 benchtime内調用了多少次 每次調用耗時(納秒) 每次調用耗記憶體 每次調用配置設定記憶體次數
比如:
mymysql 的benchmark_getadmin在1s内一共調用了2000次,每次調用使用了974622納秒,使用記憶體大小為13444byte,配置設定記憶體的alloc調用了220次
可以看出,go-mysql-driver的每個指令運作的時間是比mymysql多,但是記憶體是使用的情況卻比mymysql少。
猜測原因由于go-mysql-driver是使用預設的database/sql和database/sql/driver接口,由于接口是官方提供的,估計耗時多在方法比對上,調用記憶體方面由于是官方的database/sql來進行連接配接等配置設定,寫的會比mymysql寫的好一些。
go test -bench=".*" -c
go test -bench=".*" -cpuprofile="cpu.prof" -memprofile="mem.prof" -blockprofile="block.prof" -memprofilerate=1 -blockprofilerate=1
go tool pprof mymysql.test cpu.prof
我這裡已經将它們都生成好了并命名為諸如mymysql_cpu.svg放在github上,你也可以直接去下載下傳看
先要明白幾個名詞
sample就是“取樣”。pprof是基于取樣調查的,比如我每納秒取樣一次,收集這個時候程式的運作函數棧,知道現在是運作在那個函數中,然後把這些資訊放在pprof檔案中提供分析。
node就是函數調用資訊,哪個函數中被調用了,調用了多少次
本方法占用sample次數(占所有sample的總數)
本方法的下行方法調用次數(占所有sample的比例)
“本方法占用sample的次數”就是除了調用下行的方法之外的其他代碼占用的方法數,當然是越小越好,越小說明了除了下行的方法之外的代碼幾乎不占用cpu時間。node的大小和這個值是正相關的
“下行方法調用次數”就是下行方法的調用中占用了多少個sample。
如果上面兩個值相等,那麼“下行方法調用次數”就會被被忽略。這個一般隻出現在edges中。
比如sweepspan就是下行方法占用37個sample,本身隻占用了1個sample。
edges就是終結點
runtime.mcmp就是自身是終結點,沒有下行方法,是以下行和本方法占用的sample相等。
mymysql.test是可執行檔案名
total samples:總的統計sample(打點數)
focusing on:關注的sample。為什麼有關注sample這麼一說呢,并不是說所有的node和edges都是有用的資訊,有的不重要的node和edges是會被忽略的。focusing on samples就是除了這些不重要的node和edges之外的sample。
dropped nodes:參考focusing on。被忽略的node。
dropped edges: 參考focusing on。被忽略的edges。
ps: 這裡預設的total sample是等于focusing sample的。你在pprof的時候可以使用--ignore參數來忽略掉那些不重要的node或者edges
明白了這些就知道了,看圖應該從最大的node往小的方向看,分析下占用資源多的函數在那裡,是否可以優化這個函數或者方法。
比如可以看一下
gomysqldriver_cpu.svg這個例子
它有個比較占用sample的分支是
它的源頭在parsedsn
看到代碼裡面去,會發現是解析dsn這步的時候使用了正則,導緻運作open的時候運作速度下降了。
是以說如果parsedsn這個函數的參數不是dsn string,而是使用map直接指定username,password等,這裡的速度就會上去了。當然這其實也是不可以的,因為database/sql/driver的open方法定義的參數就是一個string。
pprof圖将代碼流程完完全全地展現在我們面前。是以說呢我們可以做這麼幾件事情:
1 根據pprof優化代碼
2 根據pprof學習一個完全陌生的開源軟體
3 根據pprof學習go的一個程式是怎麼運作的
4 項目上線前的性能測試和壓力測試(在ab之外的有一個好的選擇了)
根據以上的比較,我還是傾向于使用go-mysql-driver。原因有幾個:
1 go-mysql-driver是實作了golang标準庫database/sql的産物。底層實作比較有保證
2 go-mysql-driver雖然每個指令的運作時間比mymysql長,但是記憶體使用少得非常明顯,這點兩方算打平。
3 go-mysql-driver實作了database/sql,如果資料庫換成其他的話,不需要更改應用邏輯的代碼。
4 go-mysql-driver實作了database/sql,這個接口的設計也是非常好的,基本和php中的pdo一樣,上手和學習成本低。