<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Apr 29, 2015 at 11:12 AM, Roger Lipscombe <span dir="ltr"><<a href="mailto:roger@differentpla.net" target="_blank">roger@differentpla.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div id=":uz" class="" style="overflow:hidden">I thought of posting a message to self(), with a timestamp and then<br>
measuring the delta. I could then post another one as soon as that<br>
message is processed. Obviously, this leaves the process continually<br>
looping, which is not good.<br></div></blockquote></div><br>I don't think this should be thrown out. It is salvagable, I think, and here is how:</div><div class="gmail_extra"><br></div><div class="gmail_extra">We update our gen_server with a new element in the state record:</div><div class="gmail_extra"><br></div><div class="gmail_extra">-record(state, { ..., marker_active = false }).</div><div class="gmail_extra"><br></div><div class="gmail_extra">Whenever we get a normal message, we check this state:</div><div class="gmail_extra"><br></div><div class="gmail_extra">handle_call(Msg, From, #state { marker_active = false } = State) -></div><div class="gmail_extra">    self() ! {marker, erlang:monotonic_time()},</div><div class="gmail_extra">    handle_call(Msg, From, State#state { marker_active = true });</div><div class="gmail_extra">....</div><div class="gmail_extra"><br>Of course handle_cast/2 and handle_info/2 needs the same treatment. This means whenever there is flow in the mailbox, we enable a marker with a timestamp.</div><div class="gmail_extra"><br></div><div class="gmail_extra">Now, we handle the marker:</div><div class="gmail_extra"><br></div><div class="gmail_extra"><div class="gmail_extra">handle_info({marker, Old}, State) -></div><div class="gmail_extra">    Diff = erlang:monotonic_time() - Old,</div><div class="gmail_extra">    report_to_hdrhistogram(erlang:convert_time_unit(Diff, native, milli_seconds)),</div><div class="gmail_extra">    {noreply, State#state { marker_active = false }}</div><div class="gmail_extra">...</div><div><br></div></div><div class="gmail_extra">This means once we get a marker, we process its queue sojourn latency, but we avoid reinjecting a new marker. The next processed message will do that.</div><div class="gmail_extra"><br></div><div class="gmail_extra">In turn, if you have 1 message going in, there will be exactly one marker. But if other processes manages to enter 100 messages between a marker and the next one, then we have one marker per 100 messages. The process will never spin if there is nothing to process. An alternative is to add some sampling interval delay:</div><div class="gmail_extra"><br></div><div class="gmail_extra"><div class="gmail_extra">handle_info({marker, Old}, State) -></div><div class="gmail_extra">    Diff = erlang:monotonic_time() - Old,</div><div class="gmail_extra">    report_to_hdrhistogram(erlang:convert_time_unit(Diff, native, milli_seconds)),</div><div class="gmail_extra">    timer:send_after(50, self(), rearm_marker),</div><div class="gmail_extra">    {noreply, State};</div><div class="gmail_extra">handle_info(rearm_marker, State) -></div><div class="gmail_extra">    {noreply, State#state { marker_active = false }};</div><div class="gmail_extra">...</div><div class="gmail_extra"><br></div><div class="gmail_extra">which closes off the problem where you have markers all over the place all the time. </div><div><br></div><div>The essential idea is to use the arrival of a "normal" message as a trigger for invoking a time sojourn marker. And never have the marker itself reinject a marker so it can't cycle. In turn, there has to be a flux through your mailbox queue for the markers to get added, and if there is no flux, no marker will ever get added. The really astute reader will prove my ramblings :)</div><div><br></div>-- <br><div class="gmail_signature">J.</div>
</div></div>