Performance
Prolog indexes clauses on the first argument (SWI uses JIT multi-argument indexing).
37.1 First-argument indexing
Prolog indexes clauses on the first argument (SWI uses JIT multi-argument indexing). Distinct functors in the first argument avoid choice points:
Put the most discriminating argument first. Use jiti_list/1 (SWI) to inspect indexes.
% Good: indexing on [] vs [_|_] → deterministic
len([], 0).
len([_|T], N) :- len(T, N0), N is N0 + 1.37.2 Last-call optimization & determinism
Make recursive calls last; avoid leaving choice points (use indexing, ->, or cuts).
Check with ?- Goal. — if the top level prints true ; instead of true., a choice point remains.
deterministic/1, $/1, det/1 declarations (SWI 8.5+) assert determinism.
37.3 Avoid common inefficiencies
append/3 in loops (O(n²)) → accumulators or difference lists.
Naive reverse → accumulator reverse.
Repeated length/2 → track counts.
findall + length to count → aggregate_all(count, ...).
assert/retract for loop state → arguments.
Use memberchk/2 instead of member/2 for membership tests.
Use assoc/rbtrees/dicts instead of lists for large lookups.
Use tabling for overlapping subproblems.
Order goals: cheap & most constraining first ("fail early").
Use msort/2/sort/4 and keysort/2 (fast C implementations).
37.4 Profiling & measuring
Increase stacks: swipl --stack-limit=4g. Garbage collection is automatic (garbage_collect/0).
?- time(nrev(1000)). % inferences, CPU time, LIPS
?- profile(my_goal). % graphical/text profiler (SWI)
?- statistics(runtime, [T, _]).
?- call_time(Goal, Dict). % library(statistics)37.5 Compilation
SWI compiles clauses to a virtual machine (not WAM exactly); qsave_program/2 creates saved states.
GNU Prolog compiles to native code; SICStus has native JIT on some platforms.
library(apply_macros), :- set_prolog_flag(optimise, true) for arithmetic compilation.