为什么Node.js分析器会说大多数应用程序都在花时间在未运行的功能上?

时间:2019-02-01 20:27:03

标签: javascript node.js profiling

我有一个运行游戏逻辑的简单Node.js服务器应用程序。游戏逻辑主要由管理Actor对象的Director类管理。我正在通过生成大量的Actors(10,000)来测试和配置服务器,以查看游戏逻辑在大部分时间上的花费。我的问题是,Node.js输出告诉我,服务器上花费的大部分时间都发生在一个似乎根本没有被调用的函数中。

我对Java语言没有足够的经验,所以我可能只是不了解解释器级别的情况,但是我对构建游戏引擎非常有经验,所以我的困惑肯定是Javascript或Node分析器输出引起的。

我像这样运行Node.js分析器:

NODE_ENV=production node --prof Server.js
sed -r 's/C\:\\[^,]+/"&"/g' isolate-0000022596D596F0-v8.log | sed -r '/C\:./ { s/\\/\//g }' > converted.log
node --prof-process converted.log > profile.log

第二行是必需的,因为节点在Windows上存在一个错误,该错误会将Windows目录转换为转义字符。 profile.log文件显示以下内容:

 [Bottom up (heavy) profile]:
  Note: percentage shows a share of a particular caller in the total
  amount of its parent calls.
  Callers occupying less than 1.0% are not shown.

   ticks parent  name
  57843   60.9%  "C:/programs/nodejs/node.exe"
  46489   80.4%    "C:/programs/nodejs/node.exe"
  16070   34.6%      LazyCompile: *Actor "C:/git/tv/static/Actor.js:7:15"
  16054   99.9%        LazyCompile: *Director.step "C:/git/tv/static/Director.js:139:35"
  15585   97.1%          LazyCompile: *processTimers timers.js:220:23
    469    2.9%          LazyCompile: ~<anonymous> "C:/git/tv/Server.js:99:21"
    469  100.0%            LazyCompile: ~ontimeout timers.js:429:19
  11388   24.5%      LazyCompile: *GeometryPartitioner.addShapeComponent "C:/git/tv/static/GeometryPartitioner.js:8:59"
  11388  100.0%        LazyCompile: *Actor.stepComponents "C:/git/tv/static/Actor.js:74:42"
  11367   99.8%          LazyCompile: *Director.step "C:/git/tv/static/Director.js:139:35"
  11047   97.2%            LazyCompile: *processTimers timers.js:220:23
    320    2.8%            LazyCompile: ~<anonymous> "C:/git/tv/Server.js:99:21"

在自下而上的配置文件顶部,我看到Actor.js第7行显然造成了34.6%的工作!第二大块很有意义,因为GeometryPartitioner是我进行宽相碰撞检测的地方,但是Actor.js:7只是Actor的构造函数-甚至没有被调用!这就是Actor:7的样子:

function Actor(actorType){
    this.actorType = actorType;
    this.id = undefined;
    this.flagNullify = false;
    this.localPosition = V2();
    this.localRadians = 0;
    this.localScale = V2(1,1);
    this.rootSceneComponent = null;
    this.components         = [];
    this.sceneComponents    = [];
    this.director           = null;
    this.movementComponent  = null;
    this.gunComponent       = null;
    this.totalAabb = AxisAlignedBox();
}

我将console.log放在Actor构造函数中只是为了查看它是否实际上在Director.step中被调用(如配置文件所建议的那样),但是在主循环中它从未打印!它触发的唯一时间是在主循环开始之前构造10,000个actor时,它执行得非常快(注意:我在性能分析会话期间删除了放置在Actor构造函数中的console.log以防止10,000行垃圾邮件日志) ):

(function(){
    console.log("spawning ton of actors...");
    for(var a = 0; a < 10000; a++){
        var roid = director.spawnActor(Actor.prototype.TYPE_ROID);
        roid.setPosition(V2(
            TV.randRange(0, 1000000), 
            TV.randRange(0, 1000000)));
    }
    console.log("done!");
})();

我很困惑。后台是否发生某种事情,导致Actor对象在我不知道的情况下被构造?我现在所知道的是Director正在存储和管理Actor对象,如下所示:

function Director(context2d, netAuthorityType){
    this.actors = {};

因此,所有actor对象都存储在Director的this.actors变量中,并且我正在遍历此对象的键并访问其值以在Director.step函数中对其进行处理,如下所示:

    for(var id in this.actors){
        actorCount++;
        var actor = this.actors[id];
        actor.step(deltaSeconds);
        actor.stepComponents(deltaSeconds, geoPartitioner, gfxPartitioner);
        if(actor.flagNullify){
            cleanup.push(actor.id);
        }
    }

我只是不明白,为什么Node.js分析器输出告诉我Director正在其step函数中创建新的Actor对象,即使事实并非如此?我是否误读了Node.js的探查器输出?我在用Javascript做根本上错误的事情吗?

0 个答案:

没有答案