从 OCaml 中的软内存不足错误中恢复
Recovering from soft out-of-memory errors in OCaml
我正在用 OCaml 编写符合 ISO 标准的 Prolog 系统。为了符合 ISO/IEC 13211-1:1995,实现必须正确处理内存不足的情况:
7 Language concepts and semantics
7.12 Errors
7.12.2 Error classification
h) There shall be a Resource Error at any stage of execution when the processor has insufficient resources to complete execution. It has the form resource_error(Imp_dep_atom)
where Imp_dep_atom
denotes an implementation dependent term.
因此符合 ISO 标准的 Prolog 系统必须提供以下三个功能:
resource_error(memory)
在 运行 超出堆 space 时抛出。
resource_error(stack)
在 运行 退出调用堆栈时抛出。
- 这两个异常都可以在 Prolog 中使用内置的
catch/3
. 捕获
到目前为止,一切顺利!在 "Today's trick : memory limits with Gc alarms" [discuss.ocaml.org] 的帮助下,我能够实施 soft(应用程序级别)内存限制。
当我连续多次 运行 一个特定的查询(需要 ~60% 的内存指定为软限制)时,但是,
一些有趣的事情正在发生:
我每隔一段时间就会得到一个答案,并且 运行 每隔一段时间就会内存不足。
就 ISO 一致性而言,这种行为是可以的,但我宁愿每次都得到答案,也不愿每隔一段时间得到答案。呸!
这应该是可行的,特别是如果我达到的限制是 soft(在 OCaml 级别上自行施加)。
所以:我怎样才能强制 OCaml GC 做(甚至)比 Gc.compact
更多的工作?
您可能正在寻找类似的东西:
Gc.set {Gc.get () with Gc.space_overhead = 40}
Gc.compact
是一次性解决方案:GC 在您调用它时会做一些工作以释放 space。而且你不能让 GC 做比 Gc.compact
更多的一次性工作,以释放更多内存。在Gc.compact ()
之后,只有OCaml为堆保留的内存块中存在实时数据,如果保留的内容比实际需要的太多,则释放不需要的块等
你想要的可能是 GC 永久花费更多的时间以使用更少的内存。您可以通过设置 space_overhead
参数(可能 max_overhead
)来获得该行为。详情见relevant chapter of the OCaml documentation:
type control = {
…
mutable space_overhead : int; (*
The major GC speed is computed from this parameter. This is the memory that will be "wasted" because the GC does not immediately
collect unreachable blocks. It is expressed as a percentage of the
memory used for live data. The GC will work more (use more CPU time
and collect blocks more eagerly) if space_overhead is smaller.
Default: 80.
同一章中记录的其他 GC 参数也可能间接影响内存消耗。这完全取决于您愿意用什么来换取更少的内存使用。
我正在用 OCaml 编写符合 ISO 标准的 Prolog 系统。为了符合 ISO/IEC 13211-1:1995,实现必须正确处理内存不足的情况:
7 Language concepts and semantics
7.12 Errors
7.12.2 Error classification
h) There shall be a Resource Error at any stage of execution when the processor has insufficient resources to complete execution. It has the form
resource_error(Imp_dep_atom)
whereImp_dep_atom
denotes an implementation dependent term.
因此符合 ISO 标准的 Prolog 系统必须提供以下三个功能:
resource_error(memory)
在 运行 超出堆 space 时抛出。resource_error(stack)
在 运行 退出调用堆栈时抛出。- 这两个异常都可以在 Prolog 中使用内置的
catch/3
. 捕获
到目前为止,一切顺利!在 "Today's trick : memory limits with Gc alarms" [discuss.ocaml.org] 的帮助下,我能够实施 soft(应用程序级别)内存限制。
当我连续多次 运行 一个特定的查询(需要 ~60% 的内存指定为软限制)时,但是, 一些有趣的事情正在发生: 我每隔一段时间就会得到一个答案,并且 运行 每隔一段时间就会内存不足。
就 ISO 一致性而言,这种行为是可以的,但我宁愿每次都得到答案,也不愿每隔一段时间得到答案。呸!
这应该是可行的,特别是如果我达到的限制是 soft(在 OCaml 级别上自行施加)。
所以:我怎样才能强制 OCaml GC 做(甚至)比 Gc.compact
更多的工作?
您可能正在寻找类似的东西:
Gc.set {Gc.get () with Gc.space_overhead = 40}
Gc.compact
是一次性解决方案:GC 在您调用它时会做一些工作以释放 space。而且你不能让 GC 做比 Gc.compact
更多的一次性工作,以释放更多内存。在Gc.compact ()
之后,只有OCaml为堆保留的内存块中存在实时数据,如果保留的内容比实际需要的太多,则释放不需要的块等
你想要的可能是 GC 永久花费更多的时间以使用更少的内存。您可以通过设置 space_overhead
参数(可能 max_overhead
)来获得该行为。详情见relevant chapter of the OCaml documentation:
type control = { … mutable space_overhead : int; (*
The major GC speed is computed from this parameter. This is the memory that will be "wasted" because the GC does not immediately collect unreachable blocks. It is expressed as a percentage of the memory used for live data. The GC will work more (use more CPU time and collect blocks more eagerly) if space_overhead is smaller. Default: 80.
同一章中记录的其他 GC 参数也可能间接影响内存消耗。这完全取决于您愿意用什么来换取更少的内存使用。