您可以在 DTrace 中以多 CPU 安全的方式比较探针之间的值吗?

Posted

技术标签:

【中文标题】您可以在 DTrace 中以多 CPU 安全的方式比较探针之间的值吗?【英文标题】:Can you compare values across probes in a multi-CPU safe way in DTrace? 【发布时间】:2020-05-28 15:26:29 【问题描述】:

我正在尝试编写一个执行以下操作的 DTrace 脚本:

    每当启动一个新线程时,就增加一个计数。 每当这些线程之一退出时,减少计数,如果计数现在为零,则退出脚本。

我有这样的事情:

BEGIN 
  threads_alive = 0;


proc:::lwp-start /execname == $$1/ 
  self->started = timestamp;
  threads_alive += 1;


proc:::lwp-exit /self->started/ 
  threads_alive -= 1;
  if (threads_alive == 0) 
    exit(0);
  

但是,这不起作用,因为threads_alive 是一个标量变量,因此它不是多 CPU 安全的。这样一来,多个线程会互相覆盖对方对变量的更改。

我也尝试过使用聚合变量:

@thread_count = sum(1)
//or
@threads_entered = count();
@threads_exitted = count();

不幸的是,我还没有找到能够执行 @thread_count == 0@threads_started == @threads_stopped 之类的语法。

【问题讨论】:

DTrace 不具备执行您在此处提议的那种线程安全数据共享的设施。你能提供更多关于你想要做什么的背景吗? proc:exit/execname == $$1/ exit(0) 会工作吗? -c-p 选项是否已经满足您的需求? @ahl 谢谢,这是有道理的。我希望在进程启动之前启动 dtrace,以便它可以捕获该进程的 lwp-start 探测(当我使用-c 时似乎不会发生这种情况,至少在 MacOS 上是这样)。然后我开始这个过程,并观察它直到它结束,此时我希望 dtrace 退出。 proc:::exit 似乎有效,只要我不多次运行该进程(我不打算这样做)。如果您愿意,请将其写为答案,我会接受,或者我会写一个答案。 【参考方案1】:

DTrace 不具备执行您提议的那种线程安全数据共享的功能,但您有几个选项,具体取决于您要执行的操作。

如果可执行文件名是唯一的,可以使用proc:::startproc:::exit分别探测第一个线程的开始和最后一个线程的退出:

proc:::start
/execname == $$1/

        my_pid = pid;


proc:::exit
/pid == my_pid/

        exit(0);

如果您对dtrace 使用-c 选项,则BEGIN 探测器会在相应的proc:::start 之后不久触发。在内部,dtrace -c 启动指定的 fork 指定命令,然后在以下四个点之一开始跟踪:exec(在新程序的第一条指令之前),preinit(在 ld 加载所有库之后),@987654331 @(在每个库的 _init 运行之后)或 main(就在程序的 main 函数的第一条指令之前,尽管这在 macOS 中不受支持)。

如果你使用dtrace -x evaltime=exec -c <program> BEGIN 将在程序的第一条指令执行之前触发:

# dtrace -xevaltime=exec -c /usr/bin/true -n 'BEGINts = timestamp' -n 'pid$target:::entryprintf("%dus", (timestamp - ts)/1000); exit(0); '
dtrace: description 'BEGIN' matched 1 probe
dtrace: description 'pid$target:::entry' matched 1767 probes
dtrace: pid 1848 has exited
CPU     ID                    FUNCTION:NAME
 10  16757                _dyld_start:entry 285us

285us 是由于 dtrace 在 macOS 上通过 /procptrace(2) 恢复进程所花费的时间。您可以使用BEGINpid$target::_dyld_start:entrypid$target::main:entry,而不是proc:::startproc:::lwp-start

【讨论】:

以上是关于您可以在 DTrace 中以多 CPU 安全的方式比较探针之间的值吗?的主要内容,如果未能解决你的问题,请参考以下文章

在java中以多线程方式插入或更新数据库中的多条记录

mac 以多tab的方式打开

如何在 Spark SQL 中以多列为中心?

在 NestJS 中以多对一关系添加字段

如何在 NextJS 中以多步形式传递数据?

如何在 Java 中以线程安全的方式使用 mkdirs?