【发布时间】:2015-06-28 00:49:51
【问题描述】:
我编写了以下小程序来确定当X 变得无法访问时,用于freeze(X,Goal) 等目标的内存是否被回收:
%:- 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)
).
让我们运行以下查询...
?- statistics, length(Zs,1000), big_freeze_test(1,500,Zs), statistics.
... 使用不同的 Prolog 处理器并查看内存消耗。 有什么不同!
(AMD64) SICStus Prolog 4.3.2:使用中的全局堆栈 = 108 MB (AMD64) B-Prolog 8.1:使用中的堆栈+堆 = 145 MB (i386) Ciao Prolog 1.14.2:使用中的全局堆栈 = 36 MB(~72 MB w/AMD64) (AMD64) SWI-Prolog 7.3.1:使用中的全局堆栈 = 0.5 MB (AMD64) YAProlog 6.2.2:使用中的全局堆栈 = 16 MB当使用?- length(Zs,1000), big_freeze_test(1,10000,Zs). 运行更多迭代时,我做了以下观察:
Ciao Prolog 在中止前报告
{ERROR: Memory allocation failed [in Realloc()]}。sicstus-prolog 和 b-prolog 分配越来越多,直到机器死机。
- swi-prolog 在 3.554 秒内执行所有迭代。
- yap 也执行所有迭代,但需要 36.910 秒。
任何想法为什么它适用于 SWI-Prolog 和 YAProlog,但 不适用于其他?
考虑到运行时,为什么 SWI-Prolog 比 YAProlog 高出一个数量级以上?
我的直觉倾向于“属性变量”与“垃圾收集”的相互作用。 SWI-Prolog 和 YAProlog 具有(共享?)与其他 Prolog 处理器不同的属性变量 API 和实现......而且,再一次,它可能是完全不同的东西。 谢谢!
【问题讨论】:
-
@j4nbur53。感谢您指出周期!我的意思是从根本上无法到达。我同意
freeze/2的这种“使用”既不是典型的也不是典型的,而是作为最后手段使用的一种绝望的措施:一种肮脏的黑客攻击,在某些情况下使得冻结目标的实现很多 更简单……最好不要影响内部实现或暂停机制的设计。 -
@j4nbur53:
freeze/2确实是约束的首选。太粗糙,无法可靠使用。 -
@j4nbur53。你指的是“when((nonvar(X),nonvar(Y)),foo(X,Y)), and both X, Y unreachable.”的经验时空测量,运行/ 使用不同的 Prolog 处理器?
-
如果 call_residue_vars/2 已就位,它仍将使用 ca 98 MB。另请参阅:github.com/SWI-Prolog/issues/issues/19#issuecomment-437183547
-
测量方式不好。您应该在
statistics之前调用garbage_collect。 SWI-Prolog 在调用 GC 方面非常激进,而其他系统倾向于扩展堆栈。堆栈扩展通常更快,但使用更多内存,如果您有很多线程,这尤其痛苦。可扩展线程是 SWI-Prolog 的重点。
标签: sicstus-prolog b-prolog swi-prolog yap prolog prolog-coroutining