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



我有一个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所做的就是反复调用matchinggrules下列出的函数,这些函数依次调用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,但我没有。根本就没有提到他们。为什么?它们是否可能以某种方式被优化/内联?如果是这样,我如何开始调试它?或者在输出中没有显示某些函数是否有一些限制?在这种情况下,这些限制在哪里定义?如能指点,不胜感激。

我正在运行Node v16.5.0

函数在为其收集tick样例时显示在概要文件中。由于基于样本的分析是一种统计事务,因此可能会发生一个运行时间很短的函数没有被抽样的情况。

在当前的情况下,内联是更可能的答案。运行带有--trace-turbo-inlining的node会输出一堆关于内联决策的信息。

如果我运行你发布的例子,我看到areDefinedEqual被内联到find中,因此find(和calculateOrder)在配置文件中显示得很高。仔细观察,在我分析的特定运行中,areDefinedEqual在内联之前被单个分析器捕获。