먼저 코드를 살펴보겠습니다.
https://github.com/prkty/KJ_malloc_lab/blob/main/mm_98_clean.c
해당 깃허브를 통해 전체 코드를 확인하실 수 있습니다.(주석 및 설명 추가)
위의 코드를 분석하면 다음 표와 같습니다.
| 항목 | 설명 |
|---|---|
| 할당자 종류 | 명시적 가용 리스트 방식 중 segregated free list 방식 사용 |
| 리스트 수 | LISTLIMIT = 16개의 크기별 분리 리스트 존재 |
| 삽입 정책 | 정렬된 주소 순으로 삽입 (오름차순 주소 정렬) |
| 분할 정책 | 요청된 크기보다 큰 블록은 분할되며, 일부 조건에서만 분할을 안 함(16바이트 미만일때) |
| 병합 정책 | 인접한 블록이 free이면 병합 (단, 다음 블록이 재할당 태그가 설정되어 있으면 병합하지 않음) |
| 재할당 정책 | REALLOC_BUFFER만큼의 추가 공간을 확보해 자주 재할당하는 블록의 성능 최적화 |
| 태그 사용 | 재할당에 사용되는 블록을 구분하기 위한 Reallocation Tag 사용 |
전체적인 로직은 Segregated List 과 동일합니다. 원래 해당 리스트는 85점 정도가 나옵니다. 그러나 우리가 해당 코드에서 주목해야될 점은 재할당 정책과 태그를 사용한다는 점입니다. 이 방법을 통해 98점이라는 높은 점수를 받을 수 있습니다. 밑에 내용을 참고하여 어떤 식으로 성능을 끌어올리는지 알아봅시다.
명석님께서 하신 말씀을 차용하여 말하자면, 사실상 묵시적말고 명시적이나 분리 가용 리스트에서는 배치정책인 First Fit, Best Fit, Next Fit 방식이 드라마틱한 효과를 보여주지 않습니다.
그러면 어떻게 3개의 가용 블록 관리 방식에서 제일 효율적이라고 불리우는 분리 가용 리스트의 성능을 끌어 올릴 수 있을까요?
→ 답은
명시적 리스트의 장점을 살려 가용 블럭 관리시에 free 블록만 따로 연결 리스트로 관리하여 삽입/삭제 효율증가시키고, 재할당시 Reallocation Buffer + Tag 를 통해 단편화의 위험성과 메모리 효율성을 증대하는 방법이 있습니다.
기본적인 realloc을 그냥 구현하면?
1. 매번 새로운 메모리 블록을 malloc
2. 데이터를 복사
3. 기존 블록을 free
복사 비용이 크고 → 데이터 처리속도가 떨어집니다. → 메모리 조각화(fragmentation)가 심해질 수 있습니다.
| 주요 구성 요소 | 사용된 방식 | 설명 |
|---|---|---|
| 메모리 분할 전략 | Segregated Free Lists | 크기별로 free list를 나누어 탐색 범위를 줄여 속도 향상 |
| 가용 블록 관리 | Explicit Linked List | free 블록만 따로 연결 리스트로 관리하여 삽입/삭제 효율적 |
| 할당 후 블록 분할 | Immediate Splitting | 할당한 블록에서 남는 공간이 충분하면 즉시 나눔 |
| 병합 전략 | Immediate Coalescing | free 시점에 인접 free 블록을 즉시 병합하여 조각화 방지 |
| 재할당 최적화 | Reallocation Buffer + Tag | 미래 realloc에 대비하여 buffer 확보, 확장 가능하게 구성 |
| 가상 주소 정렬 | 8바이트(64비트) 정렬 | CPU에서 요구하는 alignment 기준을 충족 |
오늘은 Reallocation Buffer에 대해서 발표를 해보고자 합니다.
Reallocation은 realloc을 할 때 비효율적인 메모리 복사, 재할당을 줄이기 위해 특정한 규칙을 적용하는 전략입니다.
기존의 realloc은 요청이 오면 매번 free하고 새 블록을 할당하고 복사합니다. 그러나 해당 방식을 쓰면, 특정한 조건에서 버퍼를 통한 해당 과정을 줄일 수있습니다. 그럼 이제 어떤식으로 구현되는지 알아보겠습니다. 밑에 그림은 흐름 파악용으로 참고하시면 좋을 것 같습니다.

new_size += REALLOC_BUFFER;
→ realloc이 자주 발생하는 경우 성능 최적화에 매우 큰 효과가 있습니다.
이득
if (block_buffer < 2 * REALLOC_BUFFER)
SET_RATAG(HDRP(NEXT_BLKP(ptr)));
이득
if (!GET_ALLOC(HDRP(NEXT_BLKP(ptr))) || !GET_SIZE(HDRP(NEXT_BLKP(ptr))))
이득
→ 결론적으로, Reallocation은 realloc 시 매번 새 블록 복사하지 않고, 최대한 현재 블록을 이용해 효율적으로 확장하려는 지능적인 최적화 전략입니다.
| 전략 | 설명 | 기대 효과 |
|---|---|---|
| Reallocation Buffer | 크기보다 약간 크게 확보 | future realloc 최적화 |
| Reallocation Tag | 다음 free 블록 예약 | 확장 가능성 보장 |
| Next Free Block 확장 | 옆 free 블록 흡수 | 복사 없이 realloc |
| memcpy fallback | 최후 수단 | 복사 비용 발생 |
[이점]
위와 같은 장점이 있습니다.
보통의 분리 맞춤은 85점대입니다. 그러나 위의 방법으로 98점까지 끌어 올릴수 있습니다.
그러면 생각해보건데, 이전 블록이 free라면 place만 이동시켜서 할당 시키면 더 최적화를 할 수 있지 않을까 싶긴합니다. 지금은 이전이 free이고 이후가 할당중일 때는 일반적인 realloc 방식과 동일하다.
라고 해서 해봤지만, 성능 저하가 심한 것 같다. 새로 배치하는 것이 더 효율적인 것으로 확인했다.