检查Erlang中的活动计时器
有没有一种简单的方法可以获取所有当前正在等待的计时器的列表,这些计时器以erlang:send_after、检查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: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>}]