检查Erlang中的活动计时器

检查Erlang中的活动计时器,erlang,Erlang,有没有一种简单的方法可以获取所有当前正在等待的计时器的列表,这些计时器以erlang:send_after、erlang:apply_after等开头。在erlang中,您可以保存send_after、aply_after等返回的引用,并使用erlang:read_timer检查它是否仍在等待(如果计时器已被取消或不再等待,则read_timer返回false)这是一种攻击,但使用:ets:tab2list(timer_tab)。对于两个计时器,它保持: ets:tab2list(timer

有没有一种简单的方法可以获取所有当前正在等待的计时器的列表,这些计时器以erlang:send_after、
erlang:apply_after
等开头。在erlang中,您可以保存send_after、aply_after等返回的引用,并使用erlang:read_timer检查它是否仍在等待(如果计时器已被取消或不再等待,则read_timer返回false)

这是一种攻击,但使用:ets:tab2list(timer_tab)。对于两个计时器,它保持:

  ets:tab2list(timer_tab).                                            
[{{1288384968923398,#Ref<0.0.0.30>},
  timeout,
  {erlang,integer_to_list,[23]}},
 {{23334621698390115688,#Ref<0.0.0.189>},
  timeout,
  {erlang,integer_to_list,[23]}}]
ets:tab2list(计时器选项卡)。
[{1288384968923398,#参考},
超时,
{erlang,整数到列表,[23]},
{{23334621698390115688,#参考},
超时,
{erlang,整数到列表[23]}]

查看崩溃转储中的代码,我认为只有在崩溃转储中才能找到所有刚刚激活的BIF计时器的列表。:-

出于调试目的,可以使用
dbg
:)

首先创建一个ets表,该表将存储所有计时器引用

1> ets:new(timer_dbg, ['public', 'named_table', 'bag']).
timer_dbg
然后创建一个dbg处理程序函数,该函数检查从erlang:send_after返回的调用,并将返回的计时器引用保存到表中

2> Fun = fun({'trace', _Pid, 'return_from', {erlang, send_after, 3}, Ref}, []) ->
2>           ets:insert(timer_dbg, {Ref}), [];
2>          (_Msg, []) ->
2>           []
2>       end.
#Fun<erl_eval.12.113037538>
对erlang:send\u after()进行一些测试调用。

6>erlang:send_after(1000,self(),{})。
#参考号
7> erlang:send_after(1000,self(),{})。
#参考号
8> erlang:send_after(1000,self(),{})。
#参考号
最后检查表是否包含这些引用:

9> ets:tab2list(timer_dbg).
[{#Ref<0.0.0.51>},{#Ref<0.0.0.43>},{#Ref<0.0.0.47>}]
9>ets:tab2list(timer_dbg)。
[{{Ref},{{Ref},{{Ref}]
通过这种方式,您将存储任何调用
erlang:send\u after()
的进程创建的所有计时器引用。您可以将它们映射到erlang:read\u timer()以过滤活动计时器

您可以以类似的方式跟踪对
send\u after
的调用。还可以匹配
取消计时器
并手动从表中删除取消的引用


此外,如果您没有消息密集型应用程序,您应该能够匹配由这些计时器触发的消息和/或功能,并从列表中删除过期的引用。

我今天遇到了跟踪计时器的同样必要性

它正在生产中,所以我不想使用dbg。这些是erlang:Timer,所以我以前的解决方案是无用的

相反,我分析了nbif_定时器参数从二进制_到_列表(erlang:system_info(info))

我相信(尚未确认),它报告了为计时器分配的内存。在我的x64系统上,它将是17个8字节的字=136字节

当系统设置大量定时器时,监控该值可清楚显示


享受

这不会给出所有计时器,但只给出我显式保存的计时器。它仅适用于
计时器
模块计时器,但不适用于使用
erlang:send\u after
erlang:apply\u after
true创建的计时器。。你是说erlang:我想你应该在后面发。有没有类似于erlang:apply_的东西?哦,你说得对,我只是从原始问题中复制函数名。实际上没有
erlang:apply_after
,只有
timer:apply_after
。你真的是指
erlang:
,而不是
timer:
?因为使用
erlang:send_after
erlang:start_timer
创建的计时器与使用
timer
模块创建的计时器完全不同,而且更轻。我的意思是
erlang:
,因为我已经知道如何处理由
timer:
:)创建的计时器。为什么需要这个?所以您也想跟踪它receive中的'after'子句?遗憾的是,没有直接的方法,但这应该足够用于测试目的。(我计划将其集成到我的属性测试中。)
6> erlang:send_after(1000, self(), {}).
#Ref<0.0.0.43>
7> erlang:send_after(1000, self(), {}).
#Ref<0.0.0.47>
8> erlang:send_after(1000, self(), {}).
#Ref<0.0.0.51>
9> ets:tab2list(timer_dbg).
[{#Ref<0.0.0.51>},{#Ref<0.0.0.43>},{#Ref<0.0.0.47>}]