为什么从另一个函数调用的函数不会显示在节点应用程序的配置文件输出中?

Why would a function called from another not show in the profile output of a node app?

我有一个 NodeJS 程序。这是一个更大程序的精简版本,其中包含很多与删除的问题无关的复杂性。它通过列表寻找匹配的对象:

/**
 * Checks that the given attributes are defined in the given dictionaries
 * and have the same value
 */
function areDefinedAndEqual(a, b, keys) {
  return (
    a &&
    b &&
    keys
      .map(function (k) {
        return a[k] && b[k] && a[k] === b[k]
      })
      .reduce(function (a, b) {
        return a && b
      }, true)
  )
}

function calculateOrder() {
  const matchingRules = [
    {
      desc: 'stuff, more stuff and different stuff',
      find: (po, dp) => areDefinedAndEqual(po, dp, ['stuff', 'more_stuff', 'different_stuff'])
    },
    {
      desc: 'stuff and different stuff',
      find: (po, dp) => areDefinedAndEqual(po, dp, ['stuff', 'different_stuff'])
    },
    {
      desc: 'just stuff',
      find: (po, dp) => areDefinedAndEqual(po, dp, ['stuff'])
    }
  ]
  let listOfStuff = []
  listOfStuff[999] = { stuff: 'Hello' }
  listOfStuff[9999] = { stuff: 'World' }
  listOfStuff[99999] = { stuff: 'Hello World' }
  // Run through lots of objects running through different rules to
  // find things that look similar to what we're searching for
  for (let i = 0; i < 100000000; i++) {
    for (let j = 0; j < matchingRules.length; j++) {
      if (matchingRules[j].find({ stuff: 'Hello World' }, listOfStuff[i])) {
        console.log(`Found match at position ${i} on ${matchingRules[j].desc}`)
      }
    }
  }
}

calculateOrder()

现在所有 calculateOrder 所做的就是重复调用 matchingRules 下列出的函数,这些函数又调用 areDefinedAndEqual 来进行一些实际检查。

现在如果我运行如下:

richard@sophia:~/cc/sheetbuilder (main) $ node --prof fred.js 
Found match at position 99999 on just stuff
richard@sophia:~/cc/sheetbuilder (main) $ 

我得到了我所期望的。到目前为止,一切都很好。 然后我可以 运行 通过 prof-process 输出的配置文件以获得更具可读性的内容。

node --prof-process isolate-0x57087f0-56563-v8.log

但是,如果我查看输出,我会看到:

 [JavaScript]:
   ticks  total  nonlib   name
   4197   46.0%   89.0%  LazyCompile: *calculateOrder /home/richard/cogcred/eng-data_pipeline_misc/sheetbuilder/fred.js:19:24

所有的时间都花在calculateOrder上了。我希望看到在各种“查找”功能和 areDefinedAndEqual 中花费大量时间,但我没有。根本没有提到他们中的任何一个。为什么?它们是否有可能以某种方式被优化掉/内联?如果是这样,我该如何开始调试呢?还是对输出中未显示的某些功能有一些限制?在哪种情况下,这些限制在哪里定义?任何指针将不胜感激。

我是 运行ning Node v16.5.0

函数在为它们收集刻度样本后会显示在配置文件中。由于基于样本的分析是一项统计事务,因此可能会发生非常短的 运行ning 函数未被采样的情况。

在手头的情况下,内联是更可能的答案。 运行 具有 --trace-turbo-inlining 的节点吐出一堆关于内联决策的信息。

如果我 运行 您发布的示例,我看到 areDefinedEqual 内联到 find,因此 find(和 calculateOrder)正在显示在个人资料上名列前茅。仔细观察,在我分析的特定 运行 中,areDefinedEqual 被单个分析器标记捕获——在它被内联之前。