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.
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.
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 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 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(_)).
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.
| 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 % |
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.
| 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 |
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.
| 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 % |