I made the following little program to determine if the memory used for goals like freeze(X,Goal)
is reclaimed when X
becomes unreachable:
%:- use_module(library(freeze)). % Ciao Prolog needs this
freeze_many([],[]).
freeze_many([_|Xs],[V|Vs]) :-
freeze(V,throw(error(uninstantiation_error(V),big_freeze_test/3))),
freeze_many(Xs,Vs).
big_freeze_test(N0,N,Zs0) :-
( N0 > N
-> true
; freeze_many(Zs0,Zs1),
N1 is N0+1,
big_freeze_test(N1,N,Zs1)
).
Let's run the following query...
?- statistics, length(Zs,1000), big_freeze_test(1,500,Zs), statistics.
... with different Prolog processors and look at memory consumption. What a difference!
(AMD64) SICStus Prolog 4.3.2 : global stack in use = 108 MB (AMD64) B-Prolog 8.1 : stack+heap in use = 145 MB (i386) Ciao Prolog 1.14.2: global stack in use = 36 MB (~72 MB w/AMD64) (AMD64) SWI-Prolog 7.3.1 : global stack in use = 0.5 MB (AMD64) YAProlog 6.2.2 : global stack in use = 16 MB
When running more iterations with ?- length(Zs,1000), big_freeze_test(1,10000,Zs).
, I made the following observations:
Ciao Prolog reports
{ERROR: Memory allocation failed [in Realloc()]}
before aborting.sicstus-prolog and b-prolog allocate more and more until the machine freezes.
- swi-prolog performs all iterations in 3.554 seconds.
- yap also performs all iterations, but takes 36.910 seconds.
Any ideas why it works with SWI-Prolog and YAProlog, but not with the other ones?
Considering runtime, how come SWI-Prolog beats YAProlog by more than an order of magnitude?
My intuition is leaning towards the interaction of "attributed variables" with "garbage collection". SWI-Prolog and YAProlog have (share?) a different attributed variable API and implementation than the other Prolog processors ... and, then again, it could be something completely different. Thank you!