root/trunk/manuals/userman/messages.html

Revision 4640, 16.0 KB (checked in by pmoura, 3 weeks ago)

Updated the Logtalk version number to 2.35.0 in preparation for the next release.

Improved compilation of source code resulting in smaller intermediate Prolog files and better performance for most back-end Prolog compilers (work in progress; meta-predicate support currently broken).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1<?xml version="1.0" encoding="utf-8"?>
2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
3    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4
5<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
6
7<head>
8    <meta http-equiv="content-type" content="application/xml+xhtml; charset=utf-8" />
9    <title>Logtalk user manual: message sending</title>
10    <link rel="stylesheet" href="../screen.css" type="text/css" media="screen"/>
11    <link rel="stylesheet" href="../print.css" type="text/css" media="print"/>
12</head>
13
14<body>
15
16<div class="top-left">Logtalk user manual</div> 
17<div class="top-right">Message sending</div>
18<div class="bottom-left"><span class="page"/></div> 
19<div class="bottom-right"><span class="page"/></div>
20<div class="navtop"><a href="../index.html">Contents</a> &gt; <a href="index.html">User Manual</a> &gt; Message sending</div>
21
22<h1 id="messages_messages">Message sending</h1>
23
24<p>
25Messages allows us to call object predicates. Logtalk uses the same nomenclature found in other object-oriented programming languages such as Smalltalk. Therefore, the terms <em>predicate</em> and <em>method</em> are often used interchangeably when refering to predicates defined inside objects and categories. A message must always match a predicate within the scope of the sender object.
26</p>
27<p>
28Note that message sending is only the same as calling an object's predicate if the object does not inherit (or import) predicate definitions from other objects (or categories). Otherwise, the predicate definition that will be executed may depend on the relationships of the object with other Logtalk entities.
29</p>
30
31<h2 id="messages_operators">Operators used in message sending</h2>
32
33<p>
34Logtalk uses the following three operators for message sending and related control constructs:
35</p>
36<pre>:- op(600, xfx, ::).
37:- op(600,  fx, ::).
38:- op(600,  fx, ^^).
39:- op(600,  fy,  :).</pre>
40<p>
41It is assumed that these operators remain active (once the Logtalk compiler and runtime files are loaded) until the end of the Prolog session (this is the usual behavior of most Prolog compilers). Note that these operator definitions are compatible with the pre-defined operators in the Prolog ISO standard.
42</p>
43
44<h2 id="messages_sending">Sending a message to an object</h2>
45
46<p>
47Sending a message to an object is accomplished by using the <a title="Consult reference manual" href="../refman/control/to_object2.html"><code>::/2</code></a> infix  operator:
48</p>
49<pre>| ?- Object::Message.</pre>
50<p>
51The message must match a public predicate declared for the receiving object or a Logtalk/Prolog built-in predicate (the message may also correspond to a protected or private predicate if the <em>sender</em> matches the predicate scope container). The Logtalk and Prolog built-in predicates are implicitly declared as object public predicates (unless redefined inside an object). Care should be taken when using Prolog built-in predicates as messages as different Prolog compilers provide different sets of built-in predicates. In particular, using a Prolog built-in meta-predicate as a message only provides meaningful results when the predicate is overloaded as a Logtalk built-in method; Prolog built-in (meta-)predicates are usually not Logtalk aware.
52</p>
53
54<h2 id="messages_broadcasting">Broadcasting</h2>
55
56<p>
57In the Logtalk context, broadcasting is interpreted as the sending of the same message to a group of objects or the sending of several messages to the same object. Both needs can be achieved by using the message sending method described above. However, for convenience, Logtalk implements an extended syntax for message sending that makes programming easier in these situations.
58</p>
59<p>
60If we wish to send several messages to the same object, we can write:
61</p>
62<pre>| ?- Object::(Message1, Message2, ...).</pre>
63<p>
64This is semantically equivalent to:
65</p>
66<pre>| ?- Object::Message1, Object::Message2, ... .</pre>
67<p>
68We can also write:
69</p>
70<pre>| ?- Object::(Message1; Message2; ...).</pre>
71<p>
72This will be semantically equivalent to writing:
73</p>
74<pre>| ?- Object::Message1; Object::Message2; ... .</pre>
75<p>
76To send the same message to a set of objects we can write:
77</p>
78<pre>| ?- (Object1, Object2, ...)::Message.</pre>
79<p>
80This will have the same semantics as:
81</p>
82<pre>| ?- Object1::Message, Object2::Message, ... .</pre>
83<p>
84If we want to use backtracking to try the same message over a set of objects we can write:
85</p>
86<pre>| ?- (Object1; Object2, ...)::Message.</pre>
87<p>
88This will be equivalent to:
89</p>
90<pre>| ?- Object1::Message; Object2::Message; ... .</pre>
91
92<h2>Sending a message to <em>self</em><a id="messages_self"></a></h2>
93
94<p>
95While defining a predicate, we sometimes need to send a message to <em>self</em>, i.e., to the same object that has received the original message. This is done in Logtalk through the <a title="Consult reference manual" href="../refman/control/to_self1.html"><code>::/1</code></a> control construct:
96</p>
97<pre>::Message</pre>
98<p>
99We can also use the broadcasting constructs with this operator:
100</p>
101<pre>::(Message1, Message2, ...)</pre>
102<p>
103or:
104</p>
105<pre>::(Message1; Message2; ...)</pre>
106<p>
107The message must match a public or protected predicate declared for the receiving object, a private predicate within the scope of the <em>sender</em>, or a Logtalk/Prolog built-in predicate otherwise an error will be thrown (see the Reference Manual for details). If the message is sent from inside a category or if we are using private inheritance, then the message may also match a private predicate.
108</p>
109
110<h2 id="messages_super">Calling an overridden predicate definition</h2>
111
112<p>
113When redefining a predicate, sometimes we need to call the inherited definition in the new code. This functionality, introduced by the Smalltalk language through the <code>super</code> primitive, is available in Logtalk using the <a title="Consult reference manual" href="../refman/control/super1.html"><code>^^/1</code></a> control construct:
114</p>
115<pre>^^Predicate</pre>
116<p>
117Most of the time we will use this operator by instantiating the pattern:
118</p>
119<pre>Predicate :-
120    ...,            % do something
121    ^^Predicate,    % call inherited definition
122    ... .           % do something more</pre>
123<p>
124This control construct may be used to call any inherited predicate definition. This control construct may be used within objects and within categories that extend other categories. In the case of categories, the lookup for the overridden predicate definition is restricted to the extended categories.
125</p>
126
127<h2 id="messages_direct">Direct calls of imported predicates</h2>
128
129<p>
130It is possible to call an imported category predicate without using the message sending mechanisms with the <a title="Consult reference manual" href="../refman/control/direct1.html"><code>:/1</code></a> control construct. Combined with static binding, this control construct allows category predicates to be called with the same performance of local object predicates.
131</p>
132
133<h2 id="messages_events">Message sending and event generation</h2>
134
135<p>
136Every message sent using <a title="Consult reference manual" href="../refman/control/to_object2.html"><code>::/2</code></a> operator generates two events, one before and one after the message execution. Messages that are sent using the <a title="Consult reference manual" href="../refman/control/to_self1.html"><code>::/1</code></a> (message to <em>self</em>) operator or the <a title="Consult reference manual" href="../refman/control/super1.html"><code>^^/1</code></a> super mechanism described above do not generate any events. The rational behind this distinction is that messages to <em>self</em> and <em>super</em> calls are only used internally in the definition of methods or to execute additional messages with the same target object (represented by <em>self</em>). In other words, events are only generated when using an object's public interface; they cannot be used to break object encapsulation.
137</p>
138<p>
139If we need to generate events for a public message sent to <em>self</em>, then we just need to write something like:
140</p>
141<pre>Predicate :-
142    ...,
143    self(Self),       % get self reference
144    Self::Message,    % send a message to self using ::/2
145    ... .</pre>
146<p>
147If we also need the sender of the message to be other than the object containing the predicate definition, we can write:
148</p>
149<pre>Predicate :-
150    ...,
151    self(Self),       % send a message to self using ::/2
152    {Self::Message},  % sender will be the pseudo-object user
153    ... .</pre>
154<p>
155When events are not used, is possible to turn off event generation on a per object basis by using the <a title="Consult user manual" href="programming.html#programming_flags"><code>events/1</code></a> compiler option. See the session on <a href="events.html">event-driven programming</a> for more details.
156</p>
157
158<h2 id="messages_performance">Message sending performance</h2>
159
160<p>
161Logtalk supports both static binding and dynamic binding. Static binding is used whenever messages are sent (using <code>::/2</code>) to objects loaded separately using the <code>reload(skip)</code> compiler flag. When that is not the case (or when using <code>::/1</code>), Logtalk uses dynamic binding coupled with a caching mechanism that avoids repeated lookups of predicate declarations and predicate definitions. This is a solution common to other programming languages supporting dynamic binding. Message lookups are automatically cached the first time a message is sent. Cache entries are automatically removed when loading entities or using Logtalk dynamic features that invalidate the cached lookups.
162</p>
163<p>
164Whenever static binding is used, message sending performance is roughly the same as a predicate call in plain Prolog. When discussing Logtalk dynamic binding performance, two distinct cases should be considered: messages sent by the user from the top-level interpreter and messages sent from compiled objects. In addition, the message declaration and definition lookups may, or may not be already cached by the runtime engine. In what follows, we will assume that the message lookups are already cached.
165</p>
166
167<h3 id="messages_inferences">Translating message processing to predicate calls</h3>
168
169<p>
170In order to better understand the performance tradeoffs of using Logtalk dynamic binding when compared to plain Prolog or to Prolog module systems, is useful to translate message processing in terms of predicate calls. However, in doing this, we should keep in mind that the number of predicate calls is not necessarily proportional to the time taken to execute them.
171</p>
172<p>
173With event-suport turned on, a message sent from a compiled object to another object translates to six predicate calls:
174</p>
175<dl>
176    <dt>cache lookup</dt>
177        <dd>one predicate call to a dynamic table</dd>
178    <dt>checking for <em>before</em> events</dt>
179        <dd>two predicate calls assuming that no events are defined</dd>
180        <dd>(one of them to the built-in predicate <code>\+/1</code>)</dd>
181    <dt>method call</dt>
182        <dd>one predicate call</dd>
183    <dt>checking for <em>after</em> events</dt>
184        <dd>two predicate calls assuming that no events are defined</dd>
185        <dd>(one of them to the built-in predicate <code>\+/1</code>)</dd>
186</dl>
187<p>
188Given that events can be dynamically defined at runtime, there is no room for reducing the number of predicate calls without turning off support for event-driven programming. When events are defined, the number of predicate calls grows proportional to the number of events and event handlers (monitors). Event-driven programming support can be switched off for specific object using the compiler flag <a title="Consult compiler flag details" href="programming.html#programming_flags"><code>events/1</code></a>. Doing so, reduces the number of predicate calls from six to just two.
189</p>
190<p>
191Messages to <em>self</em> and <em>super</em> calls are transparent regarding events and, as such, imply only two predicate calls (the cache lookup and the method call itself).
192</p>
193<p>
194When a message is sent by the user from the top-level interpreter, Logtalk needs to perform a runtime translation of the message term in order to prove the corresponding goal. Thus, while sending a message from a compiled object corresponds to either six predicate calls (event-support on) or two predicate calls (event-support off), the same message sent by the user from the top-level interpreter necessarily implies an overhead. Considering the time taken for the user to type the goal and read the reply, this overhead is of no practical consequence.
195</p>
196<p>
197When a message is not cached, the number of predicate calls depends on the number of steps needed for the Logtalk runtime engine to lookup the corresponding predicate scope declaration (to check if the message is valid) and then to lookup a predicate definition for answering the message.
198</p>
199
200<h3 id="messages_cputime">Processing time</h3>
201
202<p>
203Not all predicate calls take the same time. Moreover, the time taken to process a specific predicate call depends on the Prolog compiler implementation details. As such, the only valid performance measure is the time taken for processing a message.
204</p>
205<p>
206The usual way of measuring the time taken by a predicate call is to repeat the call a number of times and than to calculate the average time. A sufficient large number of repetitions would hopefully lead to an accurate measure. Care should be taken to subtract the time taken by the repetition code itself. In addition, we should be aware of any limitations of the predicates used to measure execution times. One way to make sense of numbers we get is to repeat the test with the same predicate using plain Prolog and with the predicate encapsulated in a module.
207</p>
208<p>
209A simple predicate for helping benchmarking predicate calls could be:
210</p>
211<pre>benchmark(N, Goal) :-
212    repeat(N),
213        call(Goal),
214    fail.
215
216benchmark(_, _).</pre>
217<p>
218The rational of using a failure-driven loop is to try to avoid any interference on our timing measurements from garbage-collection or memory expansion mechanisms. Based on the predicate <code>benchmark/2</code>, we may define a more convenient predicate for performing our benchmarks. For example:
219</p>
220<pre>benchmark(Goal) :-
221    N = 10000000,                   % some sufficiently large number of repetitions
222    write('Number of repetitions: '), write(N), nl,
223    get_cpu_time(Seconds1),         % replace by your Prolog-specific predicate
224    benchmark(N, Goal),
225    get_cpu_time(Seconds2),
226    Average is (Seconds2 - Seconds1)/N,
227    write('Average time per call: '), write(Average), write(' seconds'), nl,
228    Speed is 1.0/Average,
229    write('Number of calls per second: '), write(Speed), nl.</pre>
230<p>
231We can get a baseline for our timings by doing:
232</p>
233<pre>| ?- benchmark(true).</pre>
234<p>
235For comparing message sending performance across several Prolog compilers, we would call the <code>benchmark/1</code> predicate with a suitable argument. For example:
236</p>
237<pre>| ?- benchmark(list::length([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], _)).</pre>
238<p>
239For comparing message sending performance with predicate calls in plain Prolog and with calls to predicates encapsulated in modules, we should use exactly the same predicate definition in the three cases.
240</p>
241<p>
242It should be stressed that message sending is only one of the factors affecting the performance of a Logtalk application (and often not the most important one). The strengths and limitations of the chosen Prolog compiler play a crucial role on all aspects of the development, reliability, usability, and performance of a Logtalk application. It is advisable to take advantage of the Logtalk wide compatibility with most Prolog compilers to test for the best match for developing your Logtalk applications.
243</p>
244
245<div class="footer">
246    <div class="copyright">
247        <span>Copyright &copy; <a href="mailto:pmoura@logtalk.org">Paulo Moura</a> &mdash; <a href="http://logtalk.org">Logtalk.org</a></span><br/> 
248        <span>Last updated on: December 18, 2008</span>
249    </div>
250    <div class="navbottom">
251        <span><a href="nomenclature.html">previous</a> | <a href="../glossary.html">glossary</a> | <a href="objects.html">next</a></span><br/>
252        <span><a href="http://validator.w3.org/check/referer">XHTML</a> + <a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a></span>
253    </div>
254</div>
255
256</body>
257
258</html>
Note: See TracBrowser for help on using the browser.