与命令行相比,C 中的 Dtrace 不会产生相同的分析结果
Dtrace from C does not yield same profiling result compared to command line
我想以编程方式从 C 跟踪堆栈 Node.js(JS 地址放在一边)。
以下命令为我提供了已解析 c++
个符号的堆栈。
sudo dtrace -C -n 'profile-101 /pid == 13221/ { ustack() }'
以下 C 代码仅 returns 地址用于 Node 的 C/C++ 代码。什么是等效的?
#include <dtrace.h>
#include <signal.h>
#include <stdio.h>
struct ps_prochandle *g_pr;
static dtrace_hdl_t* g_dtp;
static int chewrec (const dtrace_probedata_t *data, const dtrace_recdesc_t *rec, void *arg) {
// A NULL rec indicates that we've processed the last record.
if (rec == NULL) {
return (DTRACE_CONSUME_NEXT);
}
return (DTRACE_CONSUME_THIS);
}
static const char* g_prog =
"#pragma D option switchrate=1000hz\n"
"profile-1ms /pid == 13221/ {\n"
"ustack();\n"
"}";
static int g_intr;
static int g_exited;
static void intr (int signo) {
g_intr = 1;
}
int main (int argc, char** argv) {
int err;
if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
fprintf(stderr, "failed to initialize dtrace: %s\n", dtrace_errmsg(NULL, err));
return -1;
}
printf("Dtrace initialized\n");
(void) dtrace_setopt(g_dtp, "bufsize", "4m");
(void) dtrace_setopt(g_dtp, "aggsize", "4m");
printf("dtrace options set\n");
dtrace_prog_t* prog;
if ((prog = dtrace_program_strcompile(g_dtp, g_prog, DTRACE_PROBESPEC_NAME, DTRACE_C_CPP, 0, NULL)) == NULL) {
fprintf(stderr, "failed to compile dtrace program\n");
return -1;
} else {
printf("dtrace program compiled\n");
}
dtrace_proginfo_t info;
if (dtrace_program_exec(g_dtp, prog, &info) == -1) {
fprintf(stderr, "failed to enable dtrace probes\n");
return -1;
} else {
printf("dtrace probes enabled\n");
}
struct sigaction act;
(void) sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = intr;
(void) sigaction(SIGINT, &act, NULL);
(void) sigaction(SIGTERM, &act, NULL);
if (dtrace_go(g_dtp) != 0) {
fprintf(stderr, "could not start instrumentation\n");
return -1;
} else {
printf("instrumentation started ..\n");
}
int done = 0;
do {
if (!g_intr && !done) {
dtrace_sleep(g_dtp);
}
if (done || g_intr || g_exited) {
done = 1;
if (dtrace_stop(g_dtp) == -1) {
fprintf(stderr, "could not stop tracing\n");
return -1;
}
}
switch (dtrace_work(g_dtp, stdout, NULL, chewrec, NULL)) {
case DTRACE_WORKSTATUS_DONE:
done = 1;
break;
case DTRACE_WORKSTATUS_OKAY:
break;
default:
fprintf(stderr, "processing aborted");
return -1;
}
} while (!done);
printf("closing dtrace\n");
dtrace_close(g_dtp);
return 0;
}
来自 dtrace 邮件列表,Robert Mustacchi:
TL;DR resolve symbols yourself in userland.
"所以,所有的符号解析处理总是在用户空间完成。在
换句话说,内核中的 DTrace 只会收集像这样的地址
您看到的是使用 ustack 而不是 ustack 的情况
通过 jstack() 操作处理程序(jstack() 也只有 returns 个符号
非原生框架)。请注意,如果您想查看 JavaScript 具体
除了本机符号之外,您还需要使用 jstack()
在你的例子中而不是 ustack().
您可以执行这些映射的方式将根据
你在什么系统上。如果您查看 DTrace 在 illumos 上的作用
打印 ustack() 的结果
(http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libdtrace/common/dt_consume.c#1320),
然后你会看到它使用 libproc 和 Plookup_by_addr() 函数
执行翻译。尽管值得指出的是
是稳定的接口,尽管它们很少改变。"
我想以编程方式从 C 跟踪堆栈 Node.js(JS 地址放在一边)。
以下命令为我提供了已解析 c++
个符号的堆栈。
sudo dtrace -C -n 'profile-101 /pid == 13221/ { ustack() }'
以下 C 代码仅 returns 地址用于 Node 的 C/C++ 代码。什么是等效的?
#include <dtrace.h>
#include <signal.h>
#include <stdio.h>
struct ps_prochandle *g_pr;
static dtrace_hdl_t* g_dtp;
static int chewrec (const dtrace_probedata_t *data, const dtrace_recdesc_t *rec, void *arg) {
// A NULL rec indicates that we've processed the last record.
if (rec == NULL) {
return (DTRACE_CONSUME_NEXT);
}
return (DTRACE_CONSUME_THIS);
}
static const char* g_prog =
"#pragma D option switchrate=1000hz\n"
"profile-1ms /pid == 13221/ {\n"
"ustack();\n"
"}";
static int g_intr;
static int g_exited;
static void intr (int signo) {
g_intr = 1;
}
int main (int argc, char** argv) {
int err;
if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
fprintf(stderr, "failed to initialize dtrace: %s\n", dtrace_errmsg(NULL, err));
return -1;
}
printf("Dtrace initialized\n");
(void) dtrace_setopt(g_dtp, "bufsize", "4m");
(void) dtrace_setopt(g_dtp, "aggsize", "4m");
printf("dtrace options set\n");
dtrace_prog_t* prog;
if ((prog = dtrace_program_strcompile(g_dtp, g_prog, DTRACE_PROBESPEC_NAME, DTRACE_C_CPP, 0, NULL)) == NULL) {
fprintf(stderr, "failed to compile dtrace program\n");
return -1;
} else {
printf("dtrace program compiled\n");
}
dtrace_proginfo_t info;
if (dtrace_program_exec(g_dtp, prog, &info) == -1) {
fprintf(stderr, "failed to enable dtrace probes\n");
return -1;
} else {
printf("dtrace probes enabled\n");
}
struct sigaction act;
(void) sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = intr;
(void) sigaction(SIGINT, &act, NULL);
(void) sigaction(SIGTERM, &act, NULL);
if (dtrace_go(g_dtp) != 0) {
fprintf(stderr, "could not start instrumentation\n");
return -1;
} else {
printf("instrumentation started ..\n");
}
int done = 0;
do {
if (!g_intr && !done) {
dtrace_sleep(g_dtp);
}
if (done || g_intr || g_exited) {
done = 1;
if (dtrace_stop(g_dtp) == -1) {
fprintf(stderr, "could not stop tracing\n");
return -1;
}
}
switch (dtrace_work(g_dtp, stdout, NULL, chewrec, NULL)) {
case DTRACE_WORKSTATUS_DONE:
done = 1;
break;
case DTRACE_WORKSTATUS_OKAY:
break;
default:
fprintf(stderr, "processing aborted");
return -1;
}
} while (!done);
printf("closing dtrace\n");
dtrace_close(g_dtp);
return 0;
}
来自 dtrace 邮件列表,Robert Mustacchi:
TL;DR resolve symbols yourself in userland.
"所以,所有的符号解析处理总是在用户空间完成。在 换句话说,内核中的 DTrace 只会收集像这样的地址 您看到的是使用 ustack 而不是 ustack 的情况 通过 jstack() 操作处理程序(jstack() 也只有 returns 个符号 非原生框架)。请注意,如果您想查看 JavaScript 具体 除了本机符号之外,您还需要使用 jstack() 在你的例子中而不是 ustack().
您可以执行这些映射的方式将根据 你在什么系统上。如果您查看 DTrace 在 illumos 上的作用 打印 ustack() 的结果 (http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libdtrace/common/dt_consume.c#1320), 然后你会看到它使用 libproc 和 Plookup_by_addr() 函数 执行翻译。尽管值得指出的是 是稳定的接口,尽管它们很少改变。"