2010-10-29 12 views
9

C'è un modo semplice per ottenere un elenco di tutti i timer attualmente in attesa iniziati con erlang:send_after, erlang:apply_after, ecc. In Erlang?Controllare i timer attivi in ​​Erlang

+0

In realtà non c'è 'erlang: apply_after' ma solo' timer: apply_after'. Intendevi davvero 'erlang:' ma non 'timer:'? Poiché i timer creati con 'erlang: send_after' e' erlang: start_timer' sono completamente diversi e più leggeri dei timer creati con il modulo 'timer'. – hdima

+0

Intendo 'erlang:' perché sapevo già come gestire i timer creati da 'timer:' :) –

+0

Perché dovresti averne bisogno? –

risposta

5

Per il debugging è possibile utilizzare dbg :).

Prima creare una tabella ets che memorizzerà tutti i riferimenti del timer.

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

quindi creare una funzione di gestione DBG, che controlla per le chiamate di ritorno da Erlang: send_after, e salva il riferimento del timer restituito al tavolo

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> 

Impostare la funzione di gestore di traccia. consentono inoltre di corrispondenza sulla chiamata a erlang:send_after() su tutti i processi

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

Fare alcune chiamate di prova per 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> 

Infine controllare che la tabella non contiene questi riferimenti:

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

In questo modo memorizzerete tutti i riferimenti del timer creati da qualsiasi processo in qualsiasi momento chiamando lo erlang:send_after(). Puoi mapparli su erlang:read_timer() per filtrare i timer vivi.

È possibile rintracciare le chiamate su send_after in modo simile. È anche possibile abbinare su cancel_timer e rimuovere manualmente i riferimenti annullati dalla tabella.

Inoltre, se non si dispone di un'applicazione che richiede un messaggio, è possibile associare i messaggi e/o le funzioni attivati ​​da tali timer e rimuovere i riferimenti scaduti dall'elenco.

0

si potrebbe risparmiare i riferimenti restituito da send_after, aply_after ecc e l'uso Erlang: read_timer per verificare se è ancora in attesa (read_timer restituisce false se il timer è stato annullato o non è in attesa più)

+0

Questo non darà _all_ timer, ma solo quelli che ho esplicitamente salvato. –

1

Quello è un modifica ma usa: ets: tab2list (timer_tab). Per due timer in suo possesso:

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

È utile solo per i timer del modulo 'timer' ma non per i timer creati con' erlang: send_after', 'erlang: apply_after' – hdima

+0

true .. e si intende erlang: send_after solo suppongo. C'è qualcosa come erlang: apply_after any way? – user425720

+0

Oh, hai ragione, copio solo i nomi delle funzioni dalla domanda originale. – hdima

2

guardando il codice in erl_bif_timer.c penso crash dump è l'unico posto dove si può trovare un elenco di tutti i timer BIF che erano semplicemente attiva. :-)

+0

Beh, peccato :) Grazie! –

2

Oggi mi imbatto nella stessa necessità dei timer di tracciamento.

È in produzione, quindi non voglio usare dbg. Questi sono erlang: timer quindi la mia precedente soluzione è inutile.

Invece ho analizzato il parametro nbif_timer da binary_to_list (erlang: system_info (informazioni)).

Credo (non ho ancora confermato), segnala la memoria allocata per i timer. Sul mio sistema x64 sarebbero 17 parole di 8 byte = 136 byte.

Il monitoraggio di questo valore indica chiaramente quando il sistema imposta un numero elevato di timer.

divertiti.

+0

Un peccato che non ci sia un modo diretto, ma questo dovrebbe essere utilizzabile a sufficienza per scopi di test. (Ho intenzione di integrarlo nei miei test di proprietà.) – eriksoe