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
risposta
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.
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ù)
Questo non darà _all_ timer, ma solo quelli che ho esplicitamente salvato. –
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]}}]
È utile solo per i timer del modulo 'timer' ma non per i timer creati con' erlang: send_after', 'erlang: apply_after' – hdima
true .. e si intende erlang: send_after solo suppongo. C'è qualcosa come erlang: apply_after any way? – user425720
Oh, hai ragione, copio solo i nomi delle funzioni dalla domanda originale. – hdima
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. :-)
Beh, peccato :) Grazie! –
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.
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
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
Intendo 'erlang:' perché sapevo già come gestire i timer creati da 'timer:' :) –
Perché dovresti averne bisogno? –