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.42.4 (r6128), using either static binding or dynamic binding but with optional features (including events support) disabled. This provides two relevant scenarios 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 list length and naive list reverse predicates defined in plain Prolog, in a Prolog module, and in a Logtalk object (predicate definitions are the same in all cases). The following goals are used for the first two benchmark tests:
- s11:
generate_list(30, List), my_length(List, _)- s12:
generate_list(30, List), module:mod_length(List, _)- s13:
generate_list(30, List), object::length(List, _)
- s21:
generate_list(30, List), my_nrev(List, _)- s22:
generate_list(30, List), module:mod_nrev(List, _)- s23:
generate_list(30, List), object::nrev(List, _)
These benchmark tests use a list of 30 elements as an argument to the list 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). However, these tests make use of common library predicates where static binding is easily enabled, eliminating the message sending mechanism overheads. The next two examples deal with graph search:
- s31:
maze_solve(1, 7, _)- s32:
module:mod_maze_solve(1, 7, _)- s33:
maze::solve(1, 7, _)
- s41:
graph_path(0, 4, _)- s42:
module:mod_graph_path(0, 4, _)- s43:
graph::path(0, 4, _)
When static binding is used, the performance of each set of goals is expected to be similar. The performance of Logtalk can be worse due to the overhead of the extra argument added to each compiled object predicate for carrying execution context information. This overhead depends on the Prolog abstract machine and on the optimizations used to pass unchanged arguments between 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 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(_)).
Apple MacBook Pro 15.4" Core 2 Duo 2.8GHz, 4GB RAM, MacOS X Intel 10.6.6. All results are given in number of calls per second. By default, the benchmark code repeats each goal up to 100000 times in order to get more accurate results. The last columns show the trade-off between plain Prolog and Logtalk. Dynamic binding is never used in the Prolog module tests.
| Prolog compiler | s11 | s12 | s13 | s13/s11 | s21 | s22 | s23 | s23/s21 | s31 | s32 | s33 | s33/s31 | s41 | s42 | s43 | s43/s41 |
| B-Prolog 7.4#3 | 5555556 | - | 4464286 | 80.3 % | 171674 | - | 159337 | 92.8 % | 190331 | - | 163720 | 86.0 % | 71459 | - | 53996 | 75.6 % |
| CxProlog 0.97.5 (devel) | 143221 | - | 187624 | 131.0 % | 36430 | - | 35185 | 96.6 % | 59700 | - | 57068 | 95.6 % | 14311 | - | 13613 | 95.1 % |
| ECLiPSe 6.0#168 | 2500000 | 1369863 | 2439024 | 97.6 % | 97847 | 90744 | 97182 | 99.3 % | 202429 | 194553 | 196078 | 96.7 % | 45290 | 41511 | 43975 | 97.1 % |
| GNU Prolog 1.4.0 | 147929 | - | 138889 | 93.9 % | 21299 | - | 20951 | 98.4 % | 37175 | - | 35676 | 96.0 % | 9858 | - | 9463 | 96.0 % |
| Qu-Prolog 8.12 | 434783 | - | 400000 | 92.0 % | 25773 | - | 25253 | 98.0 % | 51282 | - | 48544 | 94.7 % | 8489 | - | 8285 | 97.6 % |
| SICStus Prolog 4.1.0beta1 | 1666667 | 1666667 | 1666667 | 100.0 % | 142857 | 140845 | 138889 | 97.2 % | 208333 | 208333 | 192308 | 92.3 % | 65359 | 64103 | 54645 | 83.6 % |
| SWI-Prolog 5.11.17 (64 bits) | 434783 | 434783 | 400000 | 92.0 % | 18519 | 18519 | 17241 | 93.1 % | 83333 | 83333 | 76923 | 92.3 % | 21277 | 21277 | 19608 | 92.2 % |
| XSB 3.3+ (CVS, 64 bits) | 909091 | 862069 | 884956 | 97.3 % | 52994 | 50429 | 54496 | 102.8 % | 132450 | 129702 | 126582 | 95.6 % | 36258 | 36010 | 34072 | 94.0 % |
| YAP 6.2.0 (git, 64 bits) | 2777778 | 2702703 | 2564103 | 92.3 % | 131062 | 130208 | 128370 | 97.9 % | 352113 | 355872 | 325733 | 92.5 % | 75358 | 72464 | 71942 | 95.5 % |
| Prolog compiler | s11 | s12 | s13 | s13/s11 | s21 | s22 | s23 | s23/s21 | s31 | s32 | s33 | s33/s31 | s41 | s42 | s43 | s43/s41 |
| B-Prolog 7.4#3 | 5555556 | - | 1219512 | 22.0 % | 167785 | - | 144092 | 85.9 % | 190476 | - | 144092 | 75.6 % | 71839 | - | 51867 | 72.2 % |
| CxProlog 0.97.5 (devel) | 145860 | - | 174633 | 119.7 % | 36255 | - | 34784 | 96.0 % | 59812 | - | 55854 | 93.4 % | 14297 | - | 13579 | 95.0 % |
| ECLiPSe 6.0#168 | 2500000 | 1369863 | 847458 | 33.9 % | 98135 | 92421 | 86133 | 87.8 % | 206186 | 195695 | 159744 | 77.4 % | 45558 | 40502 | 43459 | 95.4 % |
| GNU Prolog 1.4.0 | 144928 | - | 121803 | 84.0 % | 21110 | - | 20687 | 98.0 % | 36955 | - | 34602 | 93.6 % | 9863 | - | 9446 | 95.8 % |
| Qu-Prolog 8.12 | 416667 | - | 333333 | 80.0 % | 25773 | - | 24938 | 96.8 % | 50761 | - | 45872 | 90.4 % | 8460 | - | 8026 | 94.9 % |
| SICStus Prolog 4.1.0beta1 | 1666667 | 1666667 | 1111111 | 66.7 % | 144928 | 135135 | 135135 | 93.2 % | 212766 | 208333 | 172414 | 81.0 % | 62112 | 63694 | 48780 | 78.5 % |
| SWI-Prolog 5.11.17 (64 bits) | 434783 | 434783 | 357143 | 82.1 % | 18519 | 18519 | 16949 | 91.5 % | 83333 | 83333 | 71429 | 85.7 % | 21277 | 21277 | 19608 | 92.2 % |
| XSB 3.3+ (CVS, 64 bits) | 909091 | 884956 | 694444 | 76.4 % | 53107 | 50531 | 53533 | 100.8 % | 133511 | 129366 | 120192 | 90.0 % | 35971 | 35249 | 33058 | 91.9 % |
| YAP 6.2.0 (git, 64 bits) | 2777778 | 2631579 | 2500000 | 90.0 % | 127714 | 129534 | 129702 | 101.6 % | 350877 | 347222 | 324675 | 92.5 % | 72569 | 75586 | 72939 | 100.5 % |
All results are given in number of calls per second. By default, the benchmark code repeats each goal up to 100000 times in order to get more accurate results. The last column shows the trade-off between static binding (c2) and dynamic binding (c3) when calling category predicates.
| Prolog compiler | c1 | c2 | c3 | c3/c2 |
| B-Prolog 7.4#3 | 476190 | 476190 | 344828 | 72.4 % |
| CxProlog 0.97.5 (devel) | 79153 | 79381 | 74660 | 94.1 % |
| ECLiPSe 6.0#168 | 578035 | 571429 | 403226 | 70.6 % |
| GNU Prolog 1.4.0 | 80972 | 79554 | 74460 | 93.6 % |
| Qu-Prolog 8.12 | 128205 | 126582 | 116279 | 91.9 % |
| SICStus Prolog 4.1.0beta1 | 769231 | 714286 | 555556 | 77.8 % |
| SWI-Prolog 5.11.17 (64 bits) | 181818 | 166667 | 158730 | 95.2 % |
| XSB 3.3+ (CVS, 64 bits) | 374532 | 373134 | 328947 | 88.2 % |
| YAP 6.2.0 (git, 64 bits) | 952381 | 952381 | 892857 | 93.7 % |
All results are given in number of calls per second. By default, the benchmark code repeats each goal up to 100000 times in order to get more accurate results. The last column shows the trade-off between plain Prolog (d2) and Logtalk using static binding (d3).
| Prolog compiler | d1 | d2 | d3 | d4 | d5 | d3/d2 |
| B-Prolog 7.4#3 | 4082 | 1162791 | 961538 | 411862 | 364964 | 82.7 % |
| CxProlog 0.97.5 (devel) | 976 | 123570 | 117534 | 93810 | 91586 | 95.1 % |
| ECLiPSe 6.0#168 | 4387 | 775194 | 746269 | 302115 | 303951 | 96.3 % |
| GNU Prolog 1.4.0 | 5681 | 28177 | 30618 | 28918 | 28466 | 108.7 % |
| Qu-Prolog 8.12 | 678 | 48780 | 46296 | 40000 | 39841 | 94.9 % |
| SICStus Prolog 4.1.0beta1 | 3700 | 454545 | 434783 | 312500 | 303030 | 95.7 % |
| SWI-Prolog 5.11.17 (64 bits) | 5432 | 769231 | 625000 | 384615 | 357143 | 81.2 % |
| XSB 3.3+ (CVS, 64 bits) | 1118 | 81037 | 82305 | 72886 | 70872 | 101.6 % |
| YAP 6.2.0 (git, 64 bits) | 4095 | 452489 | 438596 | 350877 | 341297 | 96.9 % |