mymysql與go-mysql-driver性能比較


mymysql和go-mysql-driver是兩個現在都很流行的go的mysql驅動,這篇文章目的是要將這兩個驅動進行一下比較

兩個mysql驅動的下載地址:

https://github.com/ziutek/mymysql

http://code.google.com/p/go-mysql-driver/

首先是性能測試

准備工作:

在mysql建表和初始化數據(db是test)

drop table if exists admin;

CREATE TABLE `admin` (
    `adminid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `username` varchar(20) NOT NULL DEFAULT '' COMMENT '后台用戶名',
    `password` char(32) NOT NULL DEFAULT '' COMMENT '密碼,md5存',
    PRIMARY KEY(`adminid`)
)
COMMENT='后台用戶信息表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

insert into admin set adminid=1, username='admin', password='21232f297a57a5a743894a0e4a801fc3';

 

兩邊的庫代碼和測試代碼

Image

已經將gomysqldriver和mymysql的代碼放到github上了,有興趣的去里面看看。

https://github.com/jianfengye/MyWorks/tree/master/gomysqltest

代碼里面注意的幾點就是我們測試了get,insert,update三個操作,並且insert的時候不指定主鍵,讓其自增,innodb的表,這樣讓mysql處理插入操作盡可能快。

 

下面運行go test -bench=".*" -v -benchmem

mymysql的表現:

Image(1)

go-mysql-driver的表現:

Image(2)

輸出的數據分析:

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寫的好一些。

下面比較兩邊的profile

在兩個項目下都調用

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

go tool pprof mymysql.test cpu.prof

go tool pprof mymysql.test cpu.prof

生成svg文件

具體可以參考我之前的一篇文章 go的pprof使用(http://www.cnblogs.com/yjf512/archive/2012/12/27/2835331.html

我這里已經將它們都生成好了並命名為諸如mymysql_cpu.svg放在github上,你也可以直接去下載看

https://github.com/jianfengye/MyWorks/tree/master/gomysqltest

怎么看svg

關於pprof這里有一篇權威文章:cpuprofile(http://google-perftools.googlecode.com/svn/trunk/doc/cpuprofile.html

 

先要明白幾個名詞

sample

sample就是“取樣”。pprof是基於取樣調查的,比如我每納秒取樣一次,收集這個時候程序的運行函數棧,知道現在是運行在那個函數中,然后把這些信息放在pprof文件中提供分析。

node

node就是函數調用信息,哪個函數中被調用了,調用了多少次

Image(3)

方法名

本方法占用sample次數(占所有sample的總數)

本方法的下行方法調用次數(占所有sample的比例)

“本方法占用sample的次數”就是除了調用下行的方法之外的其他代碼占用的方法數,當然是越小越好,越小說明了除了下行的方法之外的代碼幾乎不占用cpu時間。node的大小和這個值是正相關的

“下行方法調用次數”就是下行方法的調用中占用了多少個sample。

如果上面兩個值相等,那么“下行方法調用次數”就會被被忽略。這個一般只出現在edges中。

比如sweepspan就是下行方法占用37個sample,本身只占用了1個sample。

edges

edges就是終結點

Image(4)

runtime.mcmp就是自身是終結點,沒有下行方法,所以下行和本方法占用的sample相等。

基本信息解讀

比如:

Image(5)

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的分支是

Image(6)

它的源頭在parseDSN

看到代碼里面去,會發現是解析dsn這步的時候使用了正則,導致運行Open的時候運行速度下降了。

所以說如果parseDSN這個函數的參數不是dsn string,而是使用map直接指定username,password等,這里的速度就會上去了。當然這其實也是不可以的,因為database/sql/driver的Open方法定義的參數就是一個string。

總結:

pprof圖將代碼流程完完全全地展現在我們面前。所以說呢我們可以做這么幾件事情:

1 根據pprof優化代碼

2 根據pprof學習一個完全陌生的開源軟件

3 根據pprof學習go的一個程序是怎么運行的

4 項目上線前的性能測試和壓力測試(在ab之外的有一個好的選擇了)

mymysql和go-mysql-driver的測試總結

根據以上的比較,我還是傾向於使用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一樣,上手和學習成本低。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM