2010-10-29 4 views
9

¿Existe una forma simple de obtener una lista de todos los temporizadores actualmente en espera iniciados con erlang:send_after, erlang:apply_after, etc. en Erlang?Comprobar los temporizadores activos en Erlang

+0

Actualmente no hay 'erlang: apply_after' pero solo' timer: apply_after'. ¿Realmente quisiste decir 'erlang:' pero no 'timer:'? Porque los temporizadores creados con 'erlang: send_after' y' erlang: start_timer' son completamente diferentes y más livianos que los temporizadores creados con el módulo 'timer'. – hdima

+0

Quiero decir 'erlang:' porque ya sabía cómo lidiar con los temporizadores creados por 'timer:' :) –

+0

¿Por qué necesitarías esto? –

Respuesta

5

Para la depuración, puede usar dbg :).

Primero cree una tabla de ets que almacenará todas las referencias del temporizador.

1> ets:new(timer_dbg, ['public', 'named_table', 'bag']). 
timer_dbg 

A continuación, cree una función de controlador dbg, que comprueba las llamadas que regresan de Erlang: send_after, y guarda la referencia temporizador vuelto a la mesa

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> 

Ajuste la función como manejador de rastreo. También permite a juego en la llamada a erlang:send_after() en todos los procesos

3> dbg:tracer('process', {Fun, []}). 
{ok,<0.35.0>} 
4> dbg:p('all', 'c'). 
{ok,[{matched,[email protected],26}]} 
5> dbg:tpl(erlang, send_after, [{'_', [], [{'return_trace'}]}]). 
{ok,[{matched,[email protected],1},{saved,1}]} 

hacer algunas llamadas de prueba a erlang:send_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> 

Finalmente compruebe que la tabla contiene las referencias:

9> ets:tab2list(timer_dbg). 
[{#Ref<0.0.0.51>},{#Ref<0.0.0.43>},{#Ref<0.0.0.47>}] 

esta manera almacenará todas las referencias de temporizador creadas por cualquier proceso que alguna vez haya llamado al erlang:send_after(). Puede mapearlos en erlang:read_timer() para filtrar los temporizadores activos.

Puede rastrear llamadas a send_after de manera similar. También es posible hacer coincidir en cancel_timer y eliminar manualmente las referencias canceladas de la tabla.

Además, si no tiene una aplicación con gran cantidad de mensajes, debería ser capaz de coincidir con los mensajes y/o funciones activadas por esos temporizadores, y eliminar las referencias expiradas de la lista.

0

podría ahorrarle las referencias que devuelve send_after, aply_after etc y el uso de Erlang: read_timer para comprobar si aún está esperando (read_timer devuelve false si el temporizador ha sido cancelado o no se esperaba más)

+0

Eso no le dará a _all_ timers, pero solo a los que he guardado explícitamente. –

1

eso es una hack pero use: ets: tab2list (timer_tab). Durante dos temporizadores que posee:

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]}}] 
+1

Es útil solo para temporizadores de módulo 'timer' pero no para temporizadores creados con' erlang: send_after', 'erlang: apply_after' – hdima

+0

true .. y te refieres a erlang: send_after solo supongo. ¿Hay algo como erlang: apply_after de alguna manera? – user425720

+0

Oh, tienes razón, solo copio nombres de funciones de la pregunta original. – hdima

2

mirar el código en erl_bif_timer.c Creo volcado de bloqueo es el único lugar donde se puede encontrar una lista de todos los temporizadores BIF que eran simplemente activa. :-)

+0

Bueno, lástima :) ¡Gracias! –

2

Me encuentro con la misma necesidad de rastrear temporizadores hoy.

Está en producción, por lo que no quiero usar dbg. Estos son erlang: temporizadores, por lo que mi solución anterior es inútil.

En su lugar analicé el parámetro nbif_timer de binary_to_list (erlang: system_info (info)).

Creo (aún no lo he confirmado), informa la memoria asignada para los temporizadores. En mi sistema x64 sería 17 palabras de 8 bytes = 136 bytes.

La monitorización de este valor muestra claramente cuándo el sistema establece una gran cantidad de temporizadores.

enjoy.

+0

Lástima que no hay una forma directa, pero esto debería ser lo suficientemente útil para fines de prueba. (Planeo integrarlo en mis pruebas de propiedad). – eriksoe

Cuestiones relacionadas