<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="content-type" content="application/xml+xhtml; charset=utf-8" /> <title>Logtalk tutorial: profiling programs</title> <link rel="stylesheet" href="../screen.css" type="text/css" media="screen"/> <link rel="stylesheet" href="../print.css" type="text/css" media="print"/> </head> <body> <div class="top-left">Logtalk tutorial</div> <div class="top-right">Profiling programs</div> <div class="bottom-left"><span class="page"/></div> <div class="bottom-right"><span class="page"/></div> <div class="navtop"><a href="../index.html">contents</a> > <a href="index.html">tutorial</a></div> <h1>Profiling programs</h1> <p> In this example, we will illustrate the use of: </p> <ul> <li>events</li> <li>monitors</li> </ul> <p> by defining a simple profiler that prints the starting and ending time for processing a message sent to an object. </p> <h2>Messages as events<a id="events"></a></h2> <p> In a pure object-oriented system, all computations start by sending messages to objects. We can thus define an <em>event</em> as the sending of a message to an object. An event can then be specified by the tuple <code>(Object, Message, Sender)</code>. This definition can be refined by interpreting the sending of a message and the return of the control to the object that has sent the message as two distinct events. We call these events respectively <code>before</code> and <code>after</code>. Therefore, we end up by representing an event by the tuple <code>(Event, Object, Message, Sender)</code>. For instance, if we send the message: </p> <pre>| ?- foo::bar(X). X = 1 yes</pre> <p> the two corresponding events will be: </p> <pre>(before, foo, bar(X), user) (after, foo, bar(1), user)</pre> <p> Note that the second event is only generated if the message succeeds. If the message as a goal have multiple solutions, then one <code>after</code> event will be generated for each solution. </p> <p> Events are automatically generated by the message sending mechanisms for each public message sent using the <a title="Consult reference manual" href="../refman/control/to_object2.html"><code>::/2</code></a> operator. </p> <h2>Profilers as monitors<a id="monitors"></a></h2> <p> A monitor is an object that reacts whenever a spied event occurs. The monitor actions are defined by two event handlers: <a title="Consult reference manual" href="../refman/methods/before3.html"><code>before/3</code></a> for <code>before</code> events and <a title="Consult reference manual" href="../refman/methods/after3.html"><code>after/3</code></a> for <code>after</code> events. These predicates are automatically called by the message sending mechanisms when an event registered for the monitor occurs. These event handlers are declared as public predicates in the <code>monitoring</code> built-in protocol. </p> <p> In our example, we need a way to get the current time before and after we process a message. We will assume that we have a <code>time</code> object implementing a <code>cpu_time/1</code> predicate that returns the current CPU time for the Prolog session: </p> <pre>:- object(time). :- public(cpu_time/1). :- mode(cpu_time(-number), one). ... :- end_object.</pre> <p> Our profiler will be named <code>stop_watch</code>. It must define event handlers for the <code>before</code> and <code>after</code> events that will print the event description (object, message, and sender) and the current time: </p> <pre>:- object(stop_watch, implements(monitoring)). % event handler predicate declarations :- uses(time). before(Object, Message, Sender) :- write(Object), write(' <-- '), writeq(Message), write(' from '), write(Sender), nl, write('STARTING at '), time::cpu_time(Seconds), write(Seconds), write(' seconds'), nl. after(Object, Message, Sender) :- write(Object), write(' <-- '), writeq(Message), write(' from '), write(Sender), nl, write('ENDING at '), time::cpu_time(Seconds), write(Seconds), write(' seconds'), nl. :- end_object.</pre> <p> After compiling and loading the <code>stop_watch</code> object (and the objects that we want to profile), we can use the <a title="Consult reference manual" href="../refman/builtins/define_events5.html"><code>define_events/5</code></a> built-in predicate to set up our profiler. For example, to profile all messages that are sent to the object <code>foo</code>, we need to call the goal: </p> <pre>| ?- define_events(_, foo, _, _, stop_watch). yes</pre> <p> This call will register <code>stop_watch</code> as a monitor to all messages sent to object <code>foo</code>, for both <code>before</code> and <code>after</code> events. Note that we say "as a monitor", not "the monitor": we can have any number of monitors over the same events. </p> <p> From now on, every time we sent a message to <code>foo</code>, the <code>stop_watch</code> monitor will print the starting and ending times for the message execution. For instance: </p> <pre>| ?- foo::bar(X). foo <-- bar(X) from user STARTING at 12.87415 seconds foo <-- bar(1) from user ENDING at 12.87419 seconds X = 1 yes</pre> <p> To stop profiling the messages sent to <code>foo</code> we use the <a title="Consult reference manual" href="../refman/builtins/abolish_events5.html"><code>abolish_events/5</code></a> built-in predicate: </p> <pre>| ?- abolish_events(_, foo, _, _, stop_watch). yes</pre> <p> This call will abolish all events defined over the object <code>foo</code> assigned to the <code>stop_watch</code> monitor. </p> <h2>Summary<a id="summary"></a></h2> <ul> <li>An event is defined as the sending of a (public) message to an object.</li> </ul> <ul> <li>There are two kinds of events: <code>before</code> events, generated before a message is processed, and <code>after</code> events, generated after the message processing completed successfully.</li> </ul> <ul> <li>Any object can be declared as a monitor to any event. A monitor shall reference the <code>monitoring</code> built-in protocol in the object opening directive.</li> </ul> <ul> <li>A monitor defines event handlers, the predicates <a title="Consult reference manual" href="../refman/methods/before3.html"><code>before/3</code></a> and <a title="Consult reference manual" href="../refman/methods/after3.html"><code>after/3</code></a>, that are automatically called by the runtime engine when a spied event occurs.</li> </ul> <ul> <li>Three built-in predicates, <a title="Consult reference manual" href="../refman/builtins/define_events5.html"><code>define_events/5</code></a>, <a title="Consult reference manual" href="../refman/builtins/current_event5.html"><code>current_event/5</code></a>, and <a title="Consult reference manual" href="../refman/builtins/abolish_events5.html"><code>abolish_events/5</code></a>, enables us define, query, and abolish both events and monitors.</li> </ul> <div class="footer"> <div class="copyright"> <span>Copyright © <a href="mailto:pmoura@logtalk.org">Paulo Moura</a> — <a href="http://logtalk.org">Logtalk.org</a></span><br/> <span>Last updated on: December 11, 2006</span> </div> <div class="navbottom"> <span><a href="reflection.html">previous</a> | <a href="../glossary.html">glossary</a> | <a href="index.html">next</a></span><br/> <span><a href="http://validator.w3.org/check/referer">XHTML</a> + <a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a></span> </div> </div> </body> </html>