2013-07-18 4 views
5

mergesort 및 quicksort에 대한 벤치 마크를 수행하고 있습니다.GC가 OCaml에서 사용되지 않는 메모리를 해제하도록하려면 어떻게해야합니까?

Random_list.create, Mergesort.sort_listQuicksort.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 

, 그것은 mergesort done for 10000000 elements 후 나에게 Fatal error: exception Out_of_memory을 알려줍니다


여기 내 벤치 마크 코드입니다.

메모리가 부족합니다. 문제가 없습니다. 또한 mergesort 성공 후 출력이 Out_of_memory 발생했음을 알립니다.


I 별도로 코드와 테스트를 분할 않았다 그런 것을

:

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없이 잘 실행됩니다.


여기 내 질문 : 다음 퀵 머지 소트와 : 내 벤치 마크 코드에서

예, 시리얼 종류를했다.

실행하는 동안 l의 목록과 mergesort의 목록 및 quicksort의 목록이 생성되어야합니다.

그러나 mergesort에서 만든 목록은이어야합니다. 그 목록은 그것에 대한 어떤 언급도하지 않았습니까?

퀵 정렬 전에는 원래 l 인 주요 목록이 하나뿐입니다. 맞습니까?

왜 여전히 Out_of_memory 오류가 발생합니까?

+3

각 정렬 및 목록 생성 후에 무슨 일이 일어나는지 확인하기 위해'Gc.print_stat stdout'을 사용하는 것이 좋을 것입니다. – snf

+0

위 제안에 +1. 또한, 탄젠트 적으로 관련되어, 메모리 소비를 더 잘 이해하기 위해 다음과 같은 작은 모듈이 유용 할 수 있습니다. http://ygrek.org.ua/p/code/measure.ml – ygrek

답변

1

나는이 문제가 매우 큰 목록을 사용하고 있다는 사실에 있다고 생각한다. 가비지 컬렉터는 메모리를 관리 할 수있는 두 개의 서로 다른 힙을 유지 :

  • 작은/수명이 짧은 객체에 대한 작은 힙.
  • 주요 힙 오래 지속되는 개체 용.

마이너 힙은 정기적으로 지워지고 개체가 충분히 길면 주요 힙으로 승격됩니다.

그러나 실제로는 큰 개체는 주요 힙으로 곧장 이동합니다. 문제는 주요 힙이 일 때 세계를 중지해야한다는 것입니다. 즉 응용 프로그램을 중단하십시오. 따라서 주요 힙 수집은 응용 프로그램이 오랫동안 중지되지 않도록하기 위해 여러 단계로 수행되며 작은 힙 콜렉션만큼 자주 수행되지 않습니다.

아마도 빠른 정렬을 시작하면 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 
+2

도움이된다면 매우 놀랄 것입니다. 일반적으로 할당자는 메모리가 부족할 때 GC를 강제 실행하므로 명시 적으로 트리거하지 않아도됩니다. (사실 모든 경우의 99.9 %에서 진짜 나쁜 아이디어입니다.) –

+2

"중요한 것은 힙이 세상을 멈추게하는 것입니다. 즉, 응용 프로그램을 중단하십시오."다음 문장을 시도해도 오해의 소지가 있습니다. 그것을 분명히해라. 보조 GC는 주요 GC가하는 것보다 더 적은 것을 멈추지 않습니다. 사실 "세계를 멈추게한다"는 점진적인 주요 GC에 대한 가난한 단어 선택이지만 비 증분 인 보조 GC에 적용된다고 말할 수 있습니다. Andreas가 이미 언급했듯이, 메모리가 없다면 주요 GC는 속도를 올려야합니다. 사용 가능한 메모리 풀이 고갈 될 것으로 예상 할 때주기를 정확하게 완료하도록 속도를 조정합니다. –

+0

나는 그것이 나쁜 생각 이라는데 동의합니다. 대부분의 경우 가비지 콜렉션을 강요하지만 그것이 문제의 원인이라고 생각됩니다. 나는 틀릴 수도 있고, 테스트가 작동하지 않으면, 나는 나의 대답을 지울 것이다. 단어 선택에 관해서는 사소한 GC가 실제로 세계를 멈추지 만 매우 빠르며 GC에 대한 전체 교훈을 세울 계획이 아니 었습니다. 문제가 될 것이라고 생각되는 것을 충분히 설명 할 수 있습니다. – ChristopheLec

2

을하지만, 첫 번째 프로그램이 될 수있다, 스택 프레임에 Mergesort.sort_list lQuicksort.sort_list l에 대한 포인터가있어 첫 번째 목록이 가비지 수집되지 않도록하고 두 번째 경우에는 스택 프레임이 두 let _ = ... 사이에서 할당 해제됩니까?

관련 문제