中国领先的IT技术网站
|
|

MongoDB的JavaScript性能

mongodb使用javascript做shell, mongodb的db.eval可以提供给数据驱动与这种javascript shell类似的js接口. 这算是一种移动代码风格(Mobile Code Sytles)的架构设计吧. 我期望可以利用这个接口, 将一些处理逻辑放在mongodb的节点上运行. 避免在PHP里面多次获取和操作mongodb的数据. (这个需求类似传统数据库的存储过程)

作者:佚名来源:NOSQL中文网|2015-07-20 16:41

Tech Neo技术沙龙 | 11月25号,九州云/ZStack与您一起探讨云时代网络边界管理实践


mongodb的db.eval

mongodb使用javascript做shell, mongodb的db.eval可以提供给数据驱动与这种javascript shell类似的js接口. 这算是一种移动代码风格(Mobile Code Sytles)的架构设计吧. 我期望可以利用这个接口, 将一些处理逻辑放在mongodb的节点上运行. 避免在PHP里面多次获取和操作mongodb的数据. (这个需求类似传统数据库的存储过程)

但是测试却发现, 在mongodb里面跑javascript性能很不理想. 我写了一段测试代码, 跑10000次循环:

  1. <?php 
  2. $mongo = new Mongo("mongodb://localhost:20237/"); 
  3. $db = $mongo->selectDB("attl"); 
  4.  
  5. $echo_func = <<<JAVASCRIPT 
  6. function() { 
  7.         var str = "xxxxxxxxxxxxxxxxx0000000000"
  8.         var data = str + str + str + str; 
  9.         var data = data + data + data + data; 
  10.         var max = 10000; 
  11.         var arr = []; 
  12.         var total = 0; 
  13.  
  14.         for(var a=0; a<100; a++) { 
  15.                 for(var i=0; i<max; i++) { 
  16.                         arr.push( data + " . " + data); 
  17.                 } 
  18.                 for(var i=0; i<arr.length; i++) { 
  19.                         total += arr[i].length; 
  20.                 } 
  21.                 arr = []; 
  22.         } 
  23.         return total; 
  24. JAVASCRIPT; 
  25.  
  26. $bgtime = microtime(true); 
  27.  
  28. $echo_code = new MongoCode($echo_func); 
  29. $obj = (object)array("name"=>"dzg""values"=>array(1,2,3), "bool"=>true) ; 
  30. $arr = array(1,2,3,4,5,6,7,8); 
  31. $map = array("a"=>1, "b"=>2); 
  32. $response = $db->execute($echo_code, array($obj, $arr, $map)); 
  33. var_dump($response); 
  34.  
  35. $endtime = microtime(true); 
  36.  
  37. echo "\n time : ".($endtime - $bgtime)."\n"

执行 :

  1. php ab-mongo.php 
  2. array(2) { 
  3.   ["retval"]=>  float(867000000) 
  4.   ["ok"]=>  float(1) 
  5.  
  6. time : 6.0353651046753 

这段js居然执行6秒之久! 在其他环境下测试同样功能代码:

Google Chrome : 只需70毫秒

Firefox 5 : 只需180毫秒

用PHP 5执行类似代码: 只需630毫秒

显然相比以上测试, mongodb的javascript性能差太大了.

排除测试干扰

根据mongodb官方文档 Server-side Code Execution : Limitations of eval > Write locks 一节, 我怀疑也许是Write locks导致的. 但这种怀疑和本例关系不大, locks应该只影响并发执行, 现在的问题是一次执行都这么慢.

另外, 我还担心从PHP到mongodb的js代码传递环节慢.

于是花了两种手段排除这两个因素:

使用 db.system.js.save({_id: “mytestfunc”, value: function () { … }}); 的方式, 将测试的js代码作成mongodb支持的Stored JavaScript

使用 db.runCommand({$eval: function() {return mytestfunc();}, nolock: true}) 的方式, 进行nolock调用

结果发现问题依旧. 结论是mongodb的JavaScript执行环节有问题

  测试Mongodb + V8 JavaScript引擎

我知道Mongodb的JavaScript引擎是SpiderMonkey, 于是想尝试再编译一个v8版本的Mongodb, 准备用如下JavaScript文件测试一下.

准备测试代码

  1. function dotest() { 
  2.         var str = "xxxxxxxxxxxxxxxxx0000000000"
  3.         var data = str + str + str + str; 
  4.         var data = data + data + data + data; 
  5.         var max = 10000; 
  6.         var arr = []; 
  7.         var total = 0; 
  8.  
  9.         for(var a=0; a<100; a++) { 
  10.                 for(var i=0; i<max; i++) { 
  11.                         arr.push( data + " . " + data); 
  12.                 } 
  13.                 for(var i=0; i<arr.length; i++) { 
  14.                         total += arr[i].length; 
  15.                 } 
  16.                 arr = []; 
  17.         } 
  18.         return total; 
  19.  
  20. myecho = (typeof console !== 'undefined' && typeof console.log == 'function') ? console.log : print; 
  21.  
  22. a = new Date(); 
  23. myecho("begin:\t" + a); 
  24.  
  25. myecho("result:\t" + dotest()); 
  26.  
  27. b = new Date(); 
  28. myecho("end:\t" + b); 
  29.  
  30. myecho("total time:\t" + (b - a)); 

这个JavaScript脚本能同时跑在4种环境下:

Chrome / Firefox等浏览器环境

node js的shell

SpiderMonkey 的js shell

mongo 的js shell

我准备编译完Mongodb的v8版本后, 四个环境都比较测试一下.

编译mongodb + v8

我在OpenSuse11.4下, 用linux的包管理工具准备编译环境, 还是很容易的:

#已安装的包: g++ subversion git python

  1. sudo zypper install scons tcsh boost-devel pcre-devel readline-devel 
  2.  
  3. svn checkout http://v8.googlecode.com/svn/trunk/ v8 
  4. cd v8 
  5. scons 
  6. cd .. 
  7.  
  8. git clone git://github.com/mongodb/mongo.git 
  9. cd mongov8 
  10. scons 
  11.  
  12. #run mongodb v8 
  13. ./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 

执行测试

执行~/opt/mongov8/mongo localhost:20237 dotest.js

mongo+v8 : 93毫秒

nodejs : 68毫秒

SpiderMonkey : 442毫秒

初步结论:

mongodb + v8性能非常好, 接近node.js里面的执行性能

SpiderMonkey 1.9 比v8慢5倍

mongodb使用SpiderMonkey肯定有一些环节还存在问题, 导致mongodb+SpiderMonkey比mongodb+v8慢60多倍

也许是mongodb的SpiderMonkey版本低? 我目前还不知道mongodb的发行版内, SpiderMonkey的确切版本

我上面测试SpiderMonkey 的js命令是来自xulrunner-192

测试代码很短, 比较片面, 上面的性能倍数只是大体估计, 不是全面精确的评估。

【责任编辑:honglu TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

超级网管员——网络基础

本书全面系统地概括了计算机网络的基本理论,详细阐述了OSI模型与网络协议、网络规划与综合布线、对等网络与服务器/客户端网络、Intranet服...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊
× CTO训练营(深圳站)