Skip to content

Commit

Permalink
update gc tuning
Browse files Browse the repository at this point in the history
  • Loading branch information
sangwoo-joh committed Jul 9, 2024
1 parent 1947d7f commit 1339fa5
Showing 1 changed file with 15 additions and 4 deletions.
19 changes: 15 additions & 4 deletions book/src/garbage-collection.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ type control = {

보면 알겠지만 마이너 힙을 조절할 수 있는 파라미터는 `minor_heap_size` 하나 뿐이고 나머지는 대부분 메이저 힙에 대한 파라미터이다. 그 외에 커스텀 할당과 관련된 파라미터도 있는데 이것은 문제 풀이의 범위를 벗어나기 때문에 여기서는 제외했다.

문제 풀이에서는 (1) 최대한 마이너 힙만을 쓰거나, 아니면 (2) 메이저 힙을 쓰되 파편화 신경쓰지 않고 할당 속도를 높이는게 중요하다. 따라서 다음 두 가지 방법을 고려해볼 수 있다.
문제 풀이에서는 (1) 최대한 마이너 힙만을 쓰거나, (2) 메이저 컬렉션을 최대한 미루거나, 아니면 (3) 메이저 힙을 쓰되 파편화 신경쓰지 않고 할당 속도를 높이는게 중요하다. 따라서 가능한 세 가지 접근이 있다.

### 마이너 힙 최대화
문제의 모든 할당이 충분히 작아서 마이너 힙을 키우면 될 것 같은 경우, 다음과 같이 세팅해볼 수 있다.
Expand All @@ -110,6 +110,15 @@ type control = {
let () = Gc.set { (Gc.get ()) with Gc.minor_heap_size = 1_280_000 }
```

### 메이저 컬렉션 미루기
사실 메이저 힙에 메모리를 아예 할당하지 않는 것은 꽤 어렵다. 그것보다는, 어차피 문제 풀이에서는 테스트 셋만 통과하면 되니까, 메이저 힙 컬렉션을 아예 하지 않으면 추가적인 오버헤드가 없을 것이다. 하지만 이것은 더 예측하기 어려운데, 왜냐하면 메이저 힙 컬렉션을 안해버리면 거의 반드시 메모리 제한을 초과해버리기 때문이다.

따라서 가장 적당한 접근은 메이저 컬렉션을 *최대한 미루는* 것이다. 문제는 이것 역시 손쉽게 판단하기 어렵다는 것이다. 문제와 문제의 테스트 셋 특성에 따라서 메이저 힙의 공간 오버헤드를 얼마나 크게 가져갈 수 있을지가 다르다. 기본 값은 120 (살아있는 데이터의 120%) 인데, 문제마다 다양하게 실험해보고 적당한 값을 찾아야 한다.

```ocaml
let () = Gc.set { (Gc.get ()) with Gc.space_overhead = 1000 }
```

### 힙 압축 안하기
백준 채점용 컴파일러인 4.11.1에서는 이미 디폴트 할당 방식이 0 (Next Fit)이므로 할당 속도에는 문제가 없다. 힙 압축을 아예 꺼버리면 혹시나 발생할지 모를 힙 압축을 아예 하지 않을 수 있다.

Expand All @@ -121,8 +130,10 @@ let () = Gc.set { (Gc.get ()) with Gc.max_overhead = 1_000_001 }
### 예시
[백준 11725번](https://www.acmicpc.net/problem/11725)을 해시 테이블 + 정수 셋을 이용한 그래프로 풀면 3회 평균 297ms의 시간과 46MB 메모리가 나온다. 여기에 위의 Gc 정책을 각각 적용해보면 다음과 같다.
- 마이너 힙 최대화: 286ms / 59MB
- 메이저 컬렉션 미루기 (1000%): **221ms** / 49MB
- 힙 압축 안하기: 309ms / **46MB**
- 둘 다 적용: **266ms** / 59MB
- 둘 다 적용 + 마이너 힙 256M 워드: 274ms / 78MB
- 셋 다 적용: 250ms / 66MB

문제의 성격에 따라 당연히 다르겠지만 이 문제에서는 메이저 컬렉션만 미뤘을 때 (오버헤드 1000%) 가장 평균적인 속도가 빨랐다. 혹시 몰라서 마이너 힙 크기를 두 배 늘렸더니 메모리 사용량은 20MB 정도 늘어났지만 속도는 오히려 떨어졌기 때문에, 마이너 힙이 크다고 항상 좋은 것은 아닌 것 같다. 그리고 메이저 컬렉션을 미루기 위한 공간 오버헤드를 10,000% 이상으로 주니 메모리 초과가 발생했다.

문제의 성격에 따라 당연히 다르겠지만 여기서는 마이너 힙을 128M 워드로 하고 메이저 힙 압축을 꺼버렸을 때 가장 평균적인 속도가 빨랐다. 혹시 몰라서 마이너 힙 크기를 두 배 늘렸더니 메모리 사용량은 20MB 정도 늘어났지만 속도는 오히려 떨어졌기 때문에, 마이너 힙이 크다고 항상 좋은 것은 아닌 것 같다. 사실 정확한 측정을 하려면 수행 횟수를 최소 30번은 해야겠지만 그러긴 힘들어서 여기서는 3번의 수행만을 했기 때문에 오차 범위가 꽤 크다는 점을 염두에 두자. 그럼에도 불구하고 Gc를 튜닝하는 것이 문제 풀이 속도에 영향을 주는 것을 눈으로 확인할 수 있었기 때문에 문제에 맞게 이를 잘 활용하면 좋겠다.
사실 정확한 측정을 하려면 수행 횟수를 최소 30번은 해야겠지만 그러긴 힘들어서 여기서는 3번의 수행만을 했기 때문에 오차 범위가 꽤 크다는 점을 염두에 두자. 그럼에도 불구하고 Gc를 튜닝하는 것이 문제 풀이 속도에 영향을 주는 것을 눈으로 확인할 수 있었기 때문에 문제에 맞게 이를 잘 활용하면 좋겠다.

0 comments on commit 1339fa5

Please sign in to comment.