内容

名称

perldtrace - Perl 的 DTrace 支持

概要

# dtrace -Zn 'perl::sub-entry, perl::sub-return { trace(copyinstr(arg0)) }'
dtrace: description 'perl::sub-entry, perl::sub-return ' matched 10 probes

# perl -E 'sub outer { inner(@_) } sub inner { say shift } outer("hello")'
hello

(dtrace output)
CPU     ID                    FUNCTION:NAME
  0  75915       Perl_pp_entersub:sub-entry   BEGIN
  0  75915       Perl_pp_entersub:sub-entry   import
  0  75922      Perl_pp_leavesub:sub-return   import
  0  75922      Perl_pp_leavesub:sub-return   BEGIN
  0  75915       Perl_pp_entersub:sub-entry   outer
  0  75915       Perl_pp_entersub:sub-entry   inner
  0  75922      Perl_pp_leavesub:sub-return   inner
  0  75922      Perl_pp_leavesub:sub-return   outer

描述

DTrace 是一个用于全面系统和应用程序级跟踪的框架。Perl 是一个 DTrace 提供者,这意味着它为检测暴露了几个探针。您可以将这些探针与内核级探针以及来自其他提供者(如 MySQL)的探针结合使用,以诊断软件缺陷,甚至只是应用程序的瓶颈。

Perl 必须使用 -Dusedtrace 选项编译才能使用提供的探针。虽然 DTrace 旨在在其检测不活动时没有开销,但 Perl 的支持本身无法保证这一点,因此它在大多数系统下没有 DTrace 探针的情况下构建。一个值得注意的例外是 Mac OS X 附带一个启用了 DTrace 支持的/usr/bin/perl

历史

5.10.1

Perl 的初始 DTrace 支持已添加,提供了 sub-entrysub-return 探针。

5.14.0

sub-entrysub-return 探针获得第四个参数:函数的包名。

5.16.0

添加了 phase-change 探针。

5.18.0

添加了 op-entryloading-fileloaded-file 探针。

探针

sub-entry(SUBNAME, FILE, LINE, PACKAGE)

跟踪任何子例程的进入。请注意,所有变量都引用正在调用的子例程;目前无法从 DTrace 操作中获取有关子例程调用者的任何信息。

:*perl*::sub-entry {
    printf("%s::%s entered at %s line %d\n",
          copyinstr(arg3), copyinstr(arg0), copyinstr(arg1), arg2);
}
sub-return(SUBNAME, FILE, LINE, PACKAGE)

跟踪任何子程序的退出。请注意,所有变量都引用正在返回的子程序;目前无法从 DTrace 操作中获取有关子程序的调用者的任何信息。

:*perl*::sub-return {
    printf("%s::%s returned at %s line %d\n",
          copyinstr(arg3), copyinstr(arg0), copyinstr(arg1), arg2);
}
phase-change(NEWPHASE, OLDPHASE)

跟踪 Perl 解释器状态的变化。您可以将其内化为跟踪 Perl 的 ${^GLOBAL_PHASE} 变量的变化,尤其是因为 NEWPHASEOLDPHASE 的值是 ${^GLOBAL_PHASE} 报告的字符串。

:*perl*::phase-change {
    printf("Phase changed from %s to %s\n",
        copyinstr(arg1), copyinstr(arg0));
}
op-entry(OPNAME)

跟踪 Perl 运行循环中每个操作码的执行。此探针在执行操作码之前触发。当启用 Perl 调试器时,DTrace 探针会在调试器钩子之后触发(但在操作码本身执行之前)。

:*perl*::op-entry {
    printf("About to execute opcode %s\n", copyinstr(arg0));
}
loading-file(FILENAME)

当 Perl 即将加载单个文件时触发,无论是来自 userequire 还是 do。此探针在从磁盘读取文件之前触发。文件名参数被转换为本地文件系统路径,而不是提供 Module::Name 样式的名称。

:*perl*:loading-file {
    printf("About to load %s\n", copyinstr(arg0));
}
loaded-file(FILENAME)

当 Perl 成功加载单个文件时触发,无论是来自 userequire 还是 do。此探针在从磁盘读取文件并评估其内容后触发。文件名参数被转换为本地文件系统路径,而不是提供 Module::Name 样式的名称。

:*perl*:loaded-file {
    printf("Successfully loaded %s\n", copyinstr(arg0));
}

EXAMPLES

最常调用的函数
# dtrace -qZn 'sub-entry { @[strjoin(strjoin(copyinstr(arg3),"::"),copyinstr(arg0))] = count() } END {trunc(@, 10)}'

Class::MOP::Attribute::slots                                    400
Try::Tiny::catch                                                411
Try::Tiny::try                                                  411
Class::MOP::Instance::inline_slot_access                        451
Class::MOP::Class::Immutable::Trait:::around                    472
Class::MOP::Mixin::AttributeCore::has_initializer               496
Class::MOP::Method::Wrapped::__ANON__                           544
Class::MOP::Package::_package_stash                             737
Class::MOP::Class::initialize                                  1128
Class::MOP::get_metaclass_by_name                              1204
跟踪函数调用
# dtrace -qFZn 'sub-entry, sub-return { trace(copyinstr(arg0)) }'

0  -> Perl_pp_entersub                        BEGIN
0  <- Perl_pp_leavesub                        BEGIN
0  -> Perl_pp_entersub                        BEGIN
0    -> Perl_pp_entersub                      import
0    <- Perl_pp_leavesub                      import
0  <- Perl_pp_leavesub                        BEGIN
0  -> Perl_pp_entersub                        BEGIN
0    -> Perl_pp_entersub                      dress
0    <- Perl_pp_leavesub                      dress
0    -> Perl_pp_entersub                      dirty
0    <- Perl_pp_leavesub                      dirty
0    -> Perl_pp_entersub                      whiten
0    <- Perl_pp_leavesub                      whiten
0  <- Perl_dounwind                           BEGIN
解释器清理期间的函数调用
# dtrace -Zn 'phase-change /copyinstr(arg0) == "END"/ { self->ending = 1 } sub-entry /self->ending/ { trace(copyinstr(arg0)) }'

CPU     ID                    FUNCTION:NAME
  1  77214       Perl_pp_entersub:sub-entry   END
  1  77214       Perl_pp_entersub:sub-entry   END
  1  77214       Perl_pp_entersub:sub-entry   cleanup
  1  77214       Perl_pp_entersub:sub-entry   _force_writable
  1  77214       Perl_pp_entersub:sub-entry   _force_writable
编译时的系统调用
# dtrace -qZn 'phase-change /copyinstr(arg0) == "START"/ { self->interesting = 1 } phase-change /copyinstr(arg0) == "RUN"/ { self->interesting = 0 } syscall::: /self->interesting/ { @[probefunc] = count() } END { trunc(@, 3) }'

lseek                                                           310
read                                                            374
stat64                                                         1056
执行最多操作码的 Perl 函数
# dtrace -qZn 'sub-entry { self->fqn = strjoin(copyinstr(arg3), strjoin("::", copyinstr(arg0))) } op-entry /self->fqn != ""/ { @[self->fqn] = count() } END { trunc(@, 3) }'

warnings::unimport                                             4589
Exporter::Heavy::_rebuild_cache                                5039
Exporter::import                                              14578

REFERENCES

DTrace 动态跟踪指南

http://dtrace.org/guide/preface.html

DTrace:Oracle Solaris、Mac OS X 和 FreeBSD 中的动态跟踪

https://www.amazon.com/DTrace-Dynamic-Tracing-Solaris-FreeBSD/dp/0132091518/

另请参阅

Devel::DTrace::Provider

此 CPAN 模块允许您使用 Perl 创建应用程序级 DTrace 探针。

作者

Shawn M Moore [email protected]