2010-10-29 10 views
9

Gibt es einen einfachen Weg, um eine Liste aller aktuell wartenden Timer zu erhalten, die mit erlang:send_after, erlang:apply_after usw. in Erlang gestartet wurden?Aktive Timer in Erlang überprüfen

+0

Eigentlich gibt es kein 'erlang: apply_after' sondern nur' timer: apply_after'. Hast du wirklich 'erlang:' gemeint, aber nicht 'timer:'? Denn Timer, die mit 'erlang: send_after' und' erlang: start_timer' erstellt wurden, sind komplett anders und leichter als Timer, die mit dem 'timer' Modul erstellt wurden. – hdima

+0

Ich meine 'erlang:' weil ich bereits wusste, wie man mit Timers umgeht, die von 'timer:' erstellt wurden :) –

+0

Warum würden Sie das brauchen? –

Antwort

5

Für Debugging-Zwecke können Sie dbg :) verwenden.

Erstellen Sie zuerst eine ETS-Tabelle, in der alle Timerreferenzen gespeichert werden.

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

Dann eine DBG-Handler-Funktion erstellen, die von erlang Rückkehr für Anrufe überprüft: send_after, und speichert den zurück Timer Bezug auf die Tabelle

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> 

die Funktion als Trace-Handler-Set. Auch ermöglichen auf den Aufruf von erlang:send_after() auf alle Prozesse

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

Machen Sie einige Testanrufe zu 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> 

Schließlich überprüfen passend, dass die Tabelle diese Verweise enthält:

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

Auf diese Weise Sie speichern alle Timer-Referenzen, die jemals von einem Prozess erstellt wurden, der erlang:send_after() aufruft. Sie können sie über erlang:read_timer() abbilden, um die aktiven Timer zu filtern.

Auf ähnliche Weise können Sie Anrufe an send_after verfolgen. Es ist auch möglich, unter cancel_timer eine Übereinstimmung zu finden und die stornierten Referenzen manuell aus der Tabelle zu entfernen.

Wenn Sie nicht über eine Anwendung mit hoher Nachrichtenintensität verfügen, sollten Sie in der Lage sein, nach Nachrichten und/oder Funktionen zu suchen, die von diesen Zeitgebern ausgelöst wurden, und die abgelaufenen Referenzen aus der Liste entfernen.

0

Sie die Referenzen von send_after zurückgegeben, aply_after usw. und die Verwendung erlang retten könnte: read_timer zu prüfen, ob es noch wartet (read_timer false zurück, wenn der Timer abgebrochen wurde oder wartet nicht mehr)

+0

Das wird nicht _all_ Timer geben, sondern nur diejenigen, die ich explizit gespeichert habe. –

1

das ist ein Hack aber benutze: ets: tab2list (timer_tab). Für zwei Timer gilt:

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 ist nur nützlich für 'Timer'-Modul-Timer, aber nicht für Timer, die mit' erlang: send_after', 'erlang: apply_after' erstellt wurden. – hdima

+0

true .. und du meinst erlang: send_after nur, denke ich. Gibt es so etwas wie erlang? – user425720

+0

Oh, du hast recht, ich kopiere nur Funktionsnamen von der ursprünglichen Frage. – hdima

2

auf den Code der Suche in erl_bif_timer.c denke ich, Crash-Dump der einzige Ort ist, wo Sie eine Liste aller BIF-Timer finden kann, die gerade aktiv waren. :-)

+0

Nun, schade :) Danke! –

2

Ich laufe heute auf die gleiche Notwendigkeit von Tracking-Timern.

Es ist auf Produktion, also möchte ich nicht dbg verwenden. Dies sind Erlang: Timer, so dass meine vorherige Lösung nutzlos ist.

Stattdessen analysierte ich nbif_timer Parameter von binary_to_list (erlang: system_info (info)).

Ich glaube (noch nicht bestätigt), es meldet Speicher für Timer zugeordnet. Auf meinem System x64 wären es 17 Wörter mit 8 Bytes = 136 Bytes.

Die Überwachung dieses Wertes zeigt deutlich an, wenn das System eine hohe Anzahl von Timern einstellt.

genießen.

+0

Schade, dass es keinen direkten Weg gibt, der aber für Testzwecke nutzbar genug sein sollte. (Ich plane, es in meine Eigentests zu integrieren.) – eriksoe