目錄

名稱

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 準備載入個別檔案時觸發,無論是來自 userequiredo。此探測會在從磁碟讀取檔案之前觸發。檔案名稱參數會轉換為本機檔案系統路徑,而不是提供 Module::Name 風格的名稱。

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

當 Perl 成功載入個別檔案時觸發,無論是來自 userequiredo。此探測會在從磁碟讀取檔案並評估其內容後觸發。檔案名稱參數會轉換為本機檔案系統路徑,而不是提供 Module::Name 風格的名稱。

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

範例

最常呼叫的函式
# 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

參考

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 sartak@gmail.com