logtalk.org
Logtalk performance

This page contains benchmark results for some Prolog compilers. The main goal of this page it to give you some data for comparing predicate performance in plain Prolog and using Logtalk objects. Benchmark results are provided for both static code and dynamic code.

Benchmark goals

All the tests have been performed using the benchmarks example distributed with Logtalk version 2.30.4, with static binding enabled and event support disabled. This provides a best case scenario for comparing Logtalk performance with plain Prolog performance. The worst case scenario corresponds to only using dynamic binding with event support enabled. The benchmarks example contains loader files for easily setting up different test scenarios.

Static code test goals

The benchmarks example provides a list length predicate (my_length/2) defined in plain Prolog and the same definition encapsulated in a Logtalk object (using the name length/2). The following goals are used for the benchmark tests:

s1: generate_list(20, List), my_length(List, _)
s2: generate_list(20, List), object::length(List, _)

When static binding is used, the performance of the two goals is expected to be similar. The performance of Logtalk can be slightly worse due to the overhead of the three extra arguments added to each compiled object predicate for carrying execution context information.

These benchmark tests use a list of 20 elements as an argument to the list length predicates. Increasing the list length may lead to decreasing performance differences between plain Prolog and Logtalk as the list length computation time starts to outweigh the overhead of the message sending mechanism. Likewise, decreasing the list length may lead to increasing performance differences between plain Prolog and Logtalk (up to the point you will be closing on the Logtalk message sending mechanism overhead when compared to plain Prolog predicate calls).

Category test goals

Category predicates can be called using either the ::/1 or the :/1 control constructs. When using the :/1 control construct, the lookup for both the predicate declaration and the predicate definition begins in this and is restricted to the imported categories. Depending on how the category is compiled, Logtalk may use static binding for :/1 calls, providing the same performance level as calls to local object predicates. The following goals are used for the benchmark tests:

c1: leaf::obj_local
c2: leaf::ctg_direct
c3: leaf::ctg_self

The obj_local method calls a local object predicate; the performance of such calls is equal or close to plain Prolog. The ctg_direct method uses the :/1 control construct to call an imported category predicate. The ctg_self method uses the ::/1 message sending control construct to call an imported category predicate. While the :/1 calls may use static binding, the ::/1 calls always use dynamic binding and a lookup caching mechanism. Note that the choice between either control construct is not simply a question of performance as the control constructs provide different semantics for calling imported category predicates. All three predicates perform the same computation (generating a list of twenty elements and calculating its length) using local predicates.

Dynamic code test goals

Dynamic code tests include both object database updates and creating and abolishing dynamic objects. The benchmarks example provides a an object named database, which defines a set of predicates for testing the Logtalk built-in database methods as described below. The following goals are used for the benchmark tests:

d1: create_object(xpto, [], [], []), abolish_object(xpto)
d2: plain_dyndb(_)
d3: database::this_dyndb(_)
d4: database::self_dyndb(_)
d5: database::obj_dyndb(_)

The first test simply creates and abolishes a (dynamic) object. The remaining tests are used for benchmarking object database updates, comparing with plain Prolog database updates. The *_dyndb tests simply assert (using assertz/1) and retract a clause (using retract/1) of a dynamic predicate with arity one. The plain_dyndb(_) test uses the Prolog built-in database predicates. The other three tests use the Logtalk built-in database methods, using a direct method call (this_dyndb(_)), a call using ::/1 (self_dyndb(_)), and a call using ::/2 (obj_dyndb(_)).

Static code benchmark results

All results are given in number of calls per second. By default, the benchmark code repeats each goal 100000 times in order to get more accurate results.

Apple MacBook Pro 15.4" Core 2 Duo 2.33GHz, 2GBMB RAM, MacOS X Intel 10.4.10
Prolog compiler  •  •  s1 •  •    •  •  s2 •  •    •  s2/s1 •  
B-Prolog 7.0 2915452 2710027 93.0 %
Ciao-Prolog 1.10#8 1207729 1183432 98.0 %
CxProlog 0.95 94073 79302 84.3 %
ECLiPSe 5.10#69 1063830 1136364 106.8 %
GNU Prolog 1.3.0 159719 136017 85.2 %
K-Prolog 5.1.5 39735 32818 82.6 %
Qu-Prolog 8.0 555556 526316 94.7 %
SICStus Prolog 4.0 1369863 1315789 96.0 %
SWI-Prolog 5.6.39 127389 115741 90.9 %
XSB 3.0.1+ (CVS) 1145475 1107420 96.7 %
YAP 5.1.3 (CVS) 3333333 3144654 94.3 %
Category benchmark results

All results are given in number of calls per second. By default, the benchmark code repeats each goal 100000 times in order to get more accurate results.

Apple MacBook Pro 15.4" Core 2 Duo 2.33GHz, 2GBMB RAM, MacOS X Intel 10.4.10
Prolog compiler  •  •  c1 •  •    •  •  c2 •  •    •  •  c3 •  •  
B-Prolog 7.0 487805 476190 371747
Ciao-Prolog 1.10#8 374532 369004 8783
CxProlog 0.95 31847 30030 29762
ECLiPSe 5.10#69 217391 212766 200000
GNU Prolog 1.3.0 52687 52138 48450
K-Prolog 5.1.5 15971 15860 15297
Qu-Prolog 8.0 101010 99010 84034
SICStus Prolog 4.0 400000 384615 344828
SWI-Prolog 5.6.39 45249 45249 43668
XSB 3.0.1+ (CVS) 314465 313480 249377
YAP 5.1.3 (CVS) 724638 719424 595238
Dynamic code benchmark results

All results are given in number of calls per second. By default, the benchmark code repeats each goal 100000 times in order to get more accurate results.

Apple MacBook Pro 15.4" Core 2 Duo 2.33GHz, 2GBMB RAM, MacOS X Intel 10.4.10
Prolog compiler  •  •  d1 •  •    •  •  d2 •  •    •  •  d3 •  •    •  •  d4 •  •    •  •  d5 •  •    •  d3/d2 •  
B-Prolog 7.0 6090 1709402 1265823 453721 439174 74.1 %
Ciao-Prolog 1.10#8 N/A 318167 289939 2371 2364 91.1 %
CxProlog 0.95 N/A 227790 157729 119048 116686 69.2 %
GNU Prolog 1.3.0 6074 12722 20333 19355 19308 159.8 %
K-Prolog 5.1.5 N/A N/A N/A N/A N/A N/A
Qu-Prolog 8.0 N/A 12136 10204 9533 9569 84.1 %
ECLiPSe 5.10#69 4044 354610 306748 248139 230947 86.5 %
SICStus Prolog 4.0 3926 265957 248756 190476 192678 93.5 %
SWI-Prolog 5.6.39 4907 689655 523560 274725 271739 75.9 %
XSB 3.0.1+ (CVS) 1108 56841 53634 48614 48130 94.4 %
YAP 5.1.3 (CVS) 1633 134445 118948 108413 101843 88.4 %
Some unsorted comments