NodeJS:为什么NodeJS c++插件这么慢



我正在尝试编写一个非常简单的nodejs c++插件,并将其使用情况与通常的nodejs模块使用情况(在CoffeeScript上编写)进行比较。我写了一个测试,从插件创建了一百万个AddonClass对象实例,从模块创建了CoffeeClass对象实例。源代码是:

addon.cpp

#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "addon_class.hpp"
using namespace v8;
static void InitAll(Handle<Object> target) {
  Addon::Init(target);
}
NODE_MODULE(addon, InitAll)

addon_class.hpp

#ifndef _ADDON_CLASS_HPP_
#define _ADDON_CLASS_HPP_
#include <node.h>
class Addon : public node::ObjectWrap {
 public:
  static void Init(v8::Handle<v8::Object> target);
 private:
  Addon(int value) : value_(value) {};
  ~Addon() {};
  static v8::Handle<v8::Value> New(const v8::Arguments& args);
  int value_;
};
#endif

addon_class.cpp

#define BUILDING_NODE_EXTENSION
#include <cstdio>
#include <node.h>
#include "addon_class.hpp"
using namespace v8;
Persistent<FunctionTemplate> tpl;
void Addon::Init(Handle<Object> target) {
  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  tpl = Persistent<FunctionTemplate>::New(t);
  tpl->SetClassName(String::NewSymbol("AddonClass"));
  tpl->InstanceTemplate()->SetInternalFieldCount(1);
  target->Set(String::NewSymbol("AddonClass"), tpl->GetFunction());
}
Handle<Value> Addon::New(const Arguments& args) {
  HandleScope scope;
  Addon* obj = new Addon(0);
  if (args[0]->IsNumber()) {
    obj->value_ = args[0]->NumberValue();
  }
  obj->Wrap(args.This());
  return args.This();
}

CoffeeClass.coffee

class CoffeeClass
  value: undefined
  constructor: (@value) ->
    if !@value? then @value = 0
exports.CoffeeClass = CoffeeClass 

benchmark.coffee

CoffeeClass = (require './CoffeeClass.coffee').CoffeeClass
AddonClass = (require './build/Release/addon.node').AddonClass
N = 1e6
calculateDiff = (d1, d2) ->
  h = parseInt d2.getHours()
  h -= parseInt d1.getHours()
  m = parseInt d2.getMinutes() + h * 60
  m -= parseInt d1.getMinutes()
  s = parseInt d2.getSeconds() + m * 60
  s -= parseInt d1.getSeconds()
  ms = parseInt d2.getMilliseconds() + s * 1000
  ms -= parseInt d1.getMilliseconds()
  return ms
testCreate = (LC) ->
  d1 = new Date()
  for i in [1..N]
    l = new LC
  d2 = new Date()
  console.log LC.name, calculateDiff(d1, d2), "ms"
testCreate(CoffeeClass)
testCreate(AddonClass)

这个基准测试的结果对我来说非常奇怪:

CoffeeClass 34 ms
AddonClass 487 ms

所以,问题是:为什么这个简单的插件这么慢?更重要的是,有没有可能用它做点什么?

这里的测试用例非常小,V8和插件之间的接口开销比编译后的c++节省的任何性能都要大。

插件的一个好用途是不健谈的东西,例如对输入参数执行复杂和优化的算法,或者与复杂的c++数据结构交互。您希望最小化对插件的调用频率,并最大限度地提高它在每次调用中所执行的工作。您甚至可以考虑将许多单独的调用一起批处理到一个数组中。

在V8 C++和JavaScript之间切换代价高昂。我想,如果您将for循环移到C++类和CoffeeScript类中,您可能会看到C++的性能优于CoffeeSript。

相关内容

  • 没有找到相关文章

最新更新