The spaceout
package, which may be loaded by the
query
| ?- use_module(library(spaceout)).
contains the predicate:
space_out(
:Goal,
+Space,
?Result)
The Goal is executed as if by call/1
. If computing any
solution causes the global stack usage to increase more than Space
bytes, the goal will be aborted and Result unified
with the atom space_out
. If the goal succeeds
without exceeding that space limit, Result is unified with
the atom success
. Space must be a positive integer.
Note that only the global stack usage is considered, i.e. the value
reported by statistics(global_stack, [Used|_])
(see State Info).
space_out/3
is implemented by raising and handling memory
resource_error
exceptions, so any exception handler in the scope
of Goal must be prepared to pass on such exceptions. Note that the
format of such exceptions varies depending on the execution mode,
Error and Exception Handling.
Before deciding whether to interrupt the computation a garbage
collection is performed to try to reduce the size of the global stack
enough to allow the computation to continue. As usual, garbage
collection can be prevented by setting the Prolog flag gc
to
off
; see State Info.
%% Call foo/0 with space_out and do not allow GC. %% Ensure the gc flag is restored when we no longer need it %% By wrapping the goal foo in once/1 we ensure that call_cleanup %% will call the clean-up goal immediately when foo succeeds. ... Size is 10*1024, % 10kB prolog_flag(gc, OldGC), call_cleanup((set_prolog_flag(gc,off), space_out(once(foo), Size, Flag)), set_prolog_flag(gc,OldGC)), %% prolog_flag(gc, OldGC) will be true here ...
The precision of space_out
can be improved by calling explicitly
garbage_collect/0
before the call to space_out/3
.
%% Call foo/0 with space_out ... Size is 10*1024, % 10kB garbage_collect, % ensure no garbage for foo/0 to use space_out(foo, Size, Flag), ( Flag == space_out -> write('foo used too much space'), nl ; write('foo used less than 10kB'), nl ), ...
A memory resource error triggered by a real out of memory
condition will not be caught by space_out/3
.
The Goal will not be interrupted before the global stack has grown by Size bytes. However, the global stack may, under unusual circumstances, grow more than Space bytes before Goal is interrupted. Such growth is unlikely to exceed 10kB.