我正在为mergesort和quicksort制定基准。
我实施了Random_list.create
,Mergesort.sort_list
并且Quicksort.sort_list
。我们可以假定这三个功能已正确实现,并且实现在此问题中并不重要。
我想问的是OCaml的GC。
这是我的基准代码:
let _ =
let l = Random_list.create 10000000 in
let len1 = List.length (Mergesort.sort_list l) in
Printf.printf "mergesort done for %d elements" len1;
let len2 = List.length (Quicksort.sort_list l) in
Printf.printf "quicksort done for %d elements" len2
如果我运行上面的代码,它将Fatal error: exception Out_of_memory
在之后告诉我mergesort done for 10000000 elements
。
它内存不足,没问题。输出也告诉我Out_of_memory
成功后发生了mergesort
。
然后,我所做的是拆分代码并分别进行测试:
let _ =
let l = Random_list.create 10000000 in
let len1 = List.length (Mergesort.sort_list l) in
Printf.printf "mergesort done for %d elements" len1
接着
let _ =
let l = Random_list.create 10000000 in
let len2 = List.length (Quicksort.sort_list l) in
Printf.printf "quicksort done for %d elements" len2
没有 两者都可以正常运行Out_of_memory
。
这是我的问题:
根据我的基准代码,是的,我进行了串行排序:mergesort,然后是quicksort。
在执行过程中,应该创建3个主要列表:l
并列列表来自mergesort和quicksort。
但是,从mergesort创建的列表应该GCed
在quicksort之前,对吗?而且该列表没有任何引用,对不对?
在进行快速排序之前,只有一个主要清单是原始清单l
,对吗?
为什么它仍然给出Out_of_memory
错误?
我认为问题在于您使用的列表非常大。垃圾收集器保留两个不同的堆来管理内存:
次要堆会定期清除,如果对象的生存期足够长,则会将其提升为主要堆。
但是,真正的大对象会直接进入主堆。问题在于,大型堆需要停止运行,即停止应用程序。因此,主要堆收集分几个步骤完成,以确保应用程序不会长时间停止,并且也不会像次要堆收集那样频繁地完成。
在您的情况下,也许在您开始快速排序时仍未收集merge_sort列表,因此所有3个列表都同时存在于内存中。
您可以要求GC进行完整的主要收集,以查看它是否可以解决问题:
let _ =
let l = Random_list.create 10000000 in
let len1 = List.length (Mergesort.sort_list l) in
Printf.printf "mergesort done for %d elements" len1;
Gc.full_major ();
let len2 = List.length (Quicksort.sort_list l) in
Printf.printf "quicksort done for %d elements" len2
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句