在 node.js --prof 输出中,这个名字奇怪的 C++ 函数在做啥?
Posted
技术标签:
【中文标题】在 node.js --prof 输出中,这个名字奇怪的 C++ 函数在做啥?【英文标题】:In node.js --prof output, what is this strangely-named C++ function doing?在 node.js --prof 输出中,这个名字奇怪的 C++ 函数在做什么? 【发布时间】:2020-02-25 05:10:38 【问题描述】:我正在分析一个经过大量修改的 JS Interpreter 分支,在 node.js v12.12.0 上运行,使用 --prof
,同时它运行一个简短的综合基准测试。在 `node --prof-process 的输出中,我看到 63% 的程序运行时花费在 C++ 中:
[Summary]:
ticks total nonlib name
1503 35.6% 35.9% javascript
2658 63.0% 63.4% C++
119 2.8% 2.8% GC
30 0.7% Shared libraries
29 0.7% Unaccounted
特别是,有一个 C++ 函数占整个运行时的 59%:
[C++]:
ticks total nonlib name
2504 59.3% 59.8% t __ZN4node9inspector8protocol11NodeRuntime14DispatcherImplD1Ev
27 0.6% 0.6% T node::native_module::NativeModuleEnv::CompileFunction(v8::FunctionCallbackInfo<v8::Value> const&)
23 0.5% 0.5% T _proc_set_dirty
16 0.4% 0.4% T __kernelrpc_vm_remap
9 0.2% 0.2% t __malloc_initialize
9 0.2% 0.2% T _thread_get_state
8 0.2% 0.2% T node::contextify::ContextifyContext::CompileFunction(v8::FunctionCallbackInfo<v8::Value> const&)
...
不幸的是,我不太清楚__ZN4node9inspector8protocol11NodeRuntime14DispatcherImplD1Ev
可能在做什么。
顾名思义,它与检查器协议有关,但我没有使用--inspect
命令行标志,也没有尝试使用检查器附加到正在运行的进程。
我似乎在 node.js 源代码中找不到任何同时包含字符串“NodeRuntime”和“DispatcherImpl”的文件。
它似乎是从几个不同的地方调用的,最常见的是从自身递归调用(列表被修剪以主要显示***条目),但命名的 JavaScript 函数没有任何明显的共性:
[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
2504 59.3% t __ZN4node9inspector8protocol11NodeRuntime14DispatcherImplD1Ev
1287 51.4% t __ZN4node9inspector8protocol11NodeRuntime14DispatcherImplD1Ev
785 61.0% LazyCompile: *intrp.Object.defineProperty /Users/cpcallen/src/CodeCity/server/interpreter.js:4477:51
226 17.6% LazyCompile: *intrp.UserFunction.instantiateDeclarations /Users/cpcallen/src/CodeCity/server/interpreter.js:4840:66
67 5.2% LazyCompile: *intrp.Object.getOwnPropertyDescriptor /Users/cpcallen/src/CodeCity/server/interpreter.js:4455:61
34 2.6% t __ZN4node9inspector8protocol11NodeRuntime14DispatcherImplD1Ev
22 1.7% LazyCompile: *stepFuncs_.MemberExpression /Users/cpcallen/src/CodeCity/server/interpreter.js:6582:42
278 11.1% LazyCompile: *Interpreter.run /Users/cpcallen/src/CodeCity/server/interpreter.js:290:37
140 5.6% LazyCompile: *stepFuncs_.Identifier /Users/cpcallen/src/CodeCity/server/interpreter.js:6494:36
121 4.8% LazyCompile: *intrp.UserFunction.instantiateDeclarations /Users/cpcallen/src/CodeCity/server/interpreter.js:4840:66
91 3.6% LazyCompile: ~runBench /Users/cpcallen/src/CodeCity/server/tests/interpreter_bench.js:37:18
79 3.2% LazyCompile: *intrp.UserFunction.call /Users/cpcallen/src/CodeCity/server/interpreter.js:4782:47
65 2.6% LazyCompile: *Interpreter.getBoundNames_ /Users/cpcallen/src/CodeCity/server/interpreter.js:2907:48
62 2.5% LazyCompile: *stepFuncs_.CallExpression /Users/cpcallen/src/CodeCity/server/interpreter.js:6039:40
我想知道它是否真的是垃圾收集器,但使用 --trace-gc
表明 GC 占用的运行时间不到总运行时间的 10%。
我怎样才能知道这个 C++ 函数在做什么?
【问题讨论】:
【参考方案1】:找到DispatcherImpl
并不难:https://github.com/nodejs/node/search?q=dispatcherimpl&unscoped_q=dispatcherimpl 直接指向https://github.com/nodejs/node/blob/5aaa7fee2e4a075d9123b885f9e8cda3de2a780a/tools/inspector_protocol/templates/TypeBuilder_cpp.template#L218。但这可能不是你真正想要的......
在一段时间内,--prof
系统中存在一个错误,C++ 滴答声会归因于错误的函数——看起来您可能会遇到这种情况。一直是fixed in V8 recently,但该修复尚未发布到 Node 版本中。
作为一种解决方法,在 Linux 上,您可以使用 perf
来分析 C++ 代码 [1],同时仍将 --prof
用于 JavaScript; --prof
的输出中的 JavaScript 滴答声以及 C++/JavaScript 分布应该是可靠正确的。在其他平台上应该有等效的通用分析技术。
[1] 有关详细信息,请阅读手册页。我通常使用类似的东西:
perf record -e cycles -F 10000 <executable and arguments>
perf report -M intel
【讨论】:
这非常有帮助,谢谢。我碰巧在 macOS 上,但看起来它也受到了影响,尽管提交描述的问题是“--prof/linux-tick-processor
中的错误”。
不幸的是,perf report
的输出信息量不是很大;列出的顶部函数是Builtins_LoadIC_Megamorphic
,仅占样本的 6.75%。也许这是正确的——这比单个 C++ 函数占用 60% 以上的 CPU 更有意义——但它并没有为主要的性能提升提供任何明显的途径。以上是关于在 node.js --prof 输出中,这个名字奇怪的 C++ 函数在做啥?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 java -prof 选项获取在 Tomcat 上运行的 java 程序的分析输出?