3

非常に単純なnodejsc++アドオンを作成し、その使用法を通常のnodejsモジュールの使用法(CoffeeScriptで記述)と比較しようとしています。addonからAddonClassの100万個のオブジェクトインスタンスを作成し、モジュールから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 

ベンチマークコーヒー

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

だから、問題は:なぜこの単純なアドオンはとても遅いのですか?そして、もっと重要なことに、それを使って何かをすることは可能ですか?

4

2 に答える 2

3

ここでのテスト ケースは非常に小さいため、V8 とアドオンの間のインターフェースのオーバーヘッドは、コンパイルされた c++ のパフォーマンスの節約よりも大きくなります。

アドオンの良い使い方は、複雑で最適化されたアルゴリズムを入力パラメーターで実行したり、複雑な C++ データ構造と対話したりするなど、おしゃべりではないものです。アドオンへの呼び出しの頻度を最小限に抑え、各呼び出しで実行される作業を最大化する必要があります。多くの個別の呼び出しをまとめて配列にバッチ処理することを検討することもできます。

于 2013-11-06T19:57:09.837 に答える
2

V8 C++ と JavaScript の間を移動するのはコストがかかります。for ループを C++ クラスと CoffeeScript クラスに移動すると、C++ が CoffeeScript よりも優れていることがわかると思います。

于 2012-12-11T20:00:29.750 に答える