MongoDB的JavaScript性能
mongodb的db.eval
mongodb使用javascript做shell, mongodb的db.eval可以提供給數(shù)據(jù)驅(qū)動(dòng)與這種javascript shell類似的js接口. 這算是一種移動(dòng)代碼風(fēng)格(Mobile Code Sytles)的架構(gòu)設(shè)計(jì)吧. 我期望可以利用這個(gè)接口, 將一些處理邏輯放在mongodb的節(jié)點(diǎn)上運(yùn)行. 避免在PHP里面多次獲取和操作mongodb的數(shù)據(jù). (這個(gè)需求類似傳統(tǒng)數(shù)據(jù)庫的存儲(chǔ)過程)
但是測(cè)試卻發(fā)現(xiàn), 在mongodb里面跑javascript性能很不理想. 我寫了一段測(cè)試代碼, 跑10000次循環(huán):
- <?php
 - $mongo = new Mongo("mongodb://localhost:20237/");
 - $db = $mongo->selectDB("attl");
 - $echo_func = <<<JAVASCRIPT
 - function() {
 - var str = "xxxxxxxxxxxxxxxxx0000000000";
 - var data = str + str + str + str;
 - var data = data + data + data + data;
 - var max = 10000;
 - var arr = [];
 - var total = 0;
 - for(var a=0; a<100; a++) {
 - for(var i=0; i<max; i++) {
 - arr.push( data + " . " + data);
 - }
 - for(var i=0; i<arr.length; i++) {
 - total += arr[i].length;
 - }
 - arr = [];
 - }
 - return total;
 - }
 - JAVASCRIPT;
 - $bgtime = microtime(true);
 - $echo_code = new MongoCode($echo_func);
 - $obj = (object)array("name"=>"dzg", "values"=>array(1,2,3), "bool"=>true) ;
 - $arr = array(1,2,3,4,5,6,7,8);
 - $map = array("a"=>1, "b"=>2);
 - $response = $db->execute($echo_code, array($obj, $arr, $map));
 - var_dump($response);
 - $endtime = microtime(true);
 - echo "\n time : ".($endtime - $bgtime)."\n";
 
執(zhí)行 :
- php ab-mongo.php
 - array(2) {
 - ["retval"]=> float(867000000)
 - ["ok"]=> float(1)
 - }
 - time : 6.0353651046753
 
這段js居然執(zhí)行6秒之久! 在其他環(huán)境下測(cè)試同樣功能代碼:
Google Chrome : 只需70毫秒
Firefox 5 : 只需180毫秒
用PHP 5執(zhí)行類似代碼: 只需630毫秒
顯然相比以上測(cè)試, mongodb的javascript性能差太大了.
排除測(cè)試干擾
根據(jù)mongodb官方文檔 Server-side Code Execution : Limitations of eval > Write locks 一節(jié), 我懷疑也許是Write locks導(dǎo)致的. 但這種懷疑和本例關(guān)系不大, locks應(yīng)該只影響并發(fā)執(zhí)行, 現(xiàn)在的問題是一次執(zhí)行都這么慢.
另外, 我還擔(dān)心從PHP到mongodb的js代碼傳遞環(huán)節(jié)慢.
于是花了兩種手段排除這兩個(gè)因素:
使用 db.system.js.save({_id: “mytestfunc”, value: function () { … }}); 的方式, 將測(cè)試的js代碼作成mongodb支持的Stored JavaScript
使用 db.runCommand({$eval: function() {return mytestfunc();}, nolock: true}) 的方式, 進(jìn)行nolock調(diào)用
結(jié)果發(fā)現(xiàn)問題依舊. 結(jié)論是mongodb的JavaScript執(zhí)行環(huán)節(jié)有問題
測(cè)試Mongodb + V8 JavaScript引擎
我知道Mongodb的JavaScript引擎是SpiderMonkey, 于是想嘗試再編譯一個(gè)v8版本的Mongodb, 準(zhǔn)備用如下JavaScript文件測(cè)試一下.
準(zhǔn)備測(cè)試代碼
- function dotest() {
 - var str = "xxxxxxxxxxxxxxxxx0000000000";
 - var data = str + str + str + str;
 - var data = data + data + data + data;
 - var max = 10000;
 - var arr = [];
 - var total = 0;
 - for(var a=0; a<100; a++) {
 - for(var i=0; i<max; i++) {
 - arr.push( data + " . " + data);
 - }
 - for(var i=0; i<arr.length; i++) {
 - total += arr[i].length;
 - }
 - arr = [];
 - }
 - return total;
 - }
 - myecho = (typeof console !== 'undefined' && typeof console.log == 'function') ? console.log : print;
 - a = new Date();
 - myecho("begin:\t" + a);
 - myecho("result:\t" + dotest());
 - b = new Date();
 - myecho("end:\t" + b);
 - myecho("total time:\t" + (b - a));
 
這個(gè)JavaScript腳本能同時(shí)跑在4種環(huán)境下:
Chrome / Firefox等瀏覽器環(huán)境
node js的shell
SpiderMonkey 的js shell
mongo 的js shell
我準(zhǔn)備編譯完Mongodb的v8版本后, 四個(gè)環(huán)境都比較測(cè)試一下.
編譯mongodb + v8
我在OpenSuse11.4下, 用linux的包管理工具準(zhǔn)備編譯環(huán)境, 還是很容易的:
#已安裝的包: g++ subversion git python
- sudo zypper install scons tcsh boost-devel pcre-devel readline-devel
 - svn checkout http://v8.googlecode.com/svn/trunk/ v8
 - cd v8
 - scons
 - cd ..
 - git clone git://github.com/mongodb/mongo.git
 - cd mongov8
 - scons
 - #run mongodb v8
 - ./mongod --quiet --shardsvr --dbpath /home/dzg/data/mongodb/test/mongod --port 20237 --nohttpinterface --fork --pidfilepath /home/dzg/data/mongodb/test/mongod.pid --logpath /home/dzg/log/mongodb/test/mongod.log --logappend
 
執(zhí)行測(cè)試
執(zhí)行~/opt/mongov8/mongo localhost:20237 dotest.js
mongo+v8 : 93毫秒
nodejs : 68毫秒
SpiderMonkey : 442毫秒
初步結(jié)論:
mongodb + v8性能非常好, 接近node.js里面的執(zhí)行性能
SpiderMonkey 1.9 比v8慢5倍
mongodb使用SpiderMonkey肯定有一些環(huán)節(jié)還存在問題, 導(dǎo)致mongodb+SpiderMonkey比mongodb+v8慢60多倍
也許是mongodb的SpiderMonkey版本低? 我目前還不知道m(xù)ongodb的發(fā)行版內(nèi), SpiderMonkey的確切版本
我上面測(cè)試SpiderMonkey 的js命令是來自xulrunner-192
測(cè)試代碼很短, 比較片面, 上面的性能倍數(shù)只是大體估計(jì), 不是全面精確的評(píng)估。















 
 
 






 
 
 
 