在 Node.js 程序上使用 DTrace 时没有函数名称

Posted

技术标签:

【中文标题】在 Node.js 程序上使用 DTrace 时没有函数名称【英文标题】:No function names when using DTrace on Node.js program 【发布时间】:2014-05-24 19:45:44 【问题描述】:

我正在尝试根据this guide 在 VirtualBox 中的 Omnios VM 上使用 DTrace 对 Node.js 程序进行 CPU 分析,我完全按照 these steps 进行设置(使用节点 0.10.26 除外)。

不幸的是,DTrace 并没有给我人类可读的 JS 函数名称,而只是原始函数地址(据我所知),看起来像这样并且不是很有帮助:

CPU     ID                    FUNCTION:NAME
  0  66407                        :tick-30s 


              node`v8::internal::String::ComputeHashField(unibrow::CharacterStream*, int, unsigned int)+0x162
              node`v8::internal::Utf8SymbolKey::Hash() [clone .part.342]+0xb9
              node`v8::internal::HashTable<v8::internal::SymbolTableShape, v8::internal::HashTableKey*>::FindEntry(v8::internal::Isolate*, v8::internal::HashTableKey*)+0x20
              node`v8::internal::SymbolTable::LookupKey(v8::internal::HashTableKey*, v8::internal::Object**)+0x38
              node`v8::internal::SymbolTable::LookupSymbol(v8::internal::Vector<char const>, v8::internal::Object**)+0x4e
              node`v8::internal::Heap::LookupSymbol(v8::internal::Vector<char const>)+0x34
              node`v8::internal::Factory::LookupSymbol(v8::internal::Vector<char const>)+0x34
              node`v8::internal::JSProxy::CallTrap(char const*, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*)+0x76
              node`v8::internal::JSProxy::GetPropertyWithHandler(v8::internal::Object*, v8::internal::String*)+0x108
              node`v8::internal::Object::GetProperty(v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, v8::internal::LookupResult*, v8::internal::Handle<v8::internal::String>, PropertyAttributes*)+0x57
              node`v8::internal::LoadIC::Load(v8::internal::InlineCacheState, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::String>)+0x49d
              node`v8::internal::LoadIC_Miss(v8::internal::Arguments, v8::internal::Isolate*)+0xbd
              0xa730a376
              0x8966eee0
              0x8968bb7c
              0xa7321899
              0xa731308a

以上是运行这些命令的结果:

dtrace -n 'profile-97/pid == 12345 && arg1/ @[jstack(150, 8000)] = count();  tick-30s  exit(0); ' > stacks.out
gc++filt < stacks.out > demangled.out

我之前没有使用 DTrace 的经验,但根据我目前收集到的信息,Node 的 ustack helper 应该将这些地址转换为可读的名称。在使用--with-dtrace 标志(我做过)构建节点时应该启用此功能,但显然它不适合我。

几乎完全相同的问题实际上是asked before,但那里接受的答案对我来说没有帮助,因为我一直在使用--dest-cpu=x64(为了确定也尝试了--dest-cpu=ia32,但确实如此没有任何区别)。

【问题讨论】:

你也可以发布你正在运行的 dtrace 命令吗? @FaridNouriNeshat 当然,将命令添加到问题中。 【参考方案1】:

想通了,感谢这篇关于 node.js+DTrace on FreeBSD 的精彩帖子。使用 DTRACE_DOF_INIT_DEBUG 标志启动节点会导致一条消息与文章中提到的可疑相似:

dtrace DOF: DTrace ioctl failed for DOF at cd5240 in /usr/local/bin/node: Arg list too long
dtrace DOF: DTrace ioctl succeeded for DOF at 1397e70 in /usr/local/bin/node

尽管这篇文章是关于 FreeBSD 的,但 DTrace 源代码的相关部分(dtrace.c 中的dtrace_dof_copyin)几乎相同(参见FreeBSD source 与OmniOS source)。因此,在我的情况下,Node ustack 帮助程序也超过了 DOF/DTrace 对象的大小限制,即使该限制在 OmniOS 中设置为 8 mb,而不是在 FreeBSD 中设置为 256 kb。

为了验证假设,我尝试了使用 Node v0.10.5 而不是 v0.10.26 的完全相同的过程,因为该版本显然至少在 3 people 之前工作过,而且它在我的案例中也起到了作用;带有上述标志的启动节点打印:

dtrace DOF: DTrace ioctl succeeded for DOF at cd6c88 in /usr/local/bin/node
dtrace DOF: DTrace ioctl succeeded for DOF at d122c8 in /usr/local/bin/node

JS 函数名称按预期出现在 DTrace 输出中。

编辑:Node v0.10.20 是它工作的最新版本。

【讨论】:

以上是关于在 Node.js 程序上使用 DTrace 时没有函数名称的主要内容,如果未能解决你的问题,请参考以下文章

dtrace 脚本输出是啥意思?

与命令行相比,来自 C 的 Dtrace 不会产生相同的分析结果

在 Oracle Linux 上使用 DTrace

哪些 DTrace 脚本值得在 Solaris 上测试和分析 Java 程序

使用单个提供程序名称为插件创建 dtrace 探针

如何在 SmartOS 上使用 HotSpot DTrace 探针?