오늘도 malloc 이다
일주일동안 하나 붙잡고 있으니…
오히려 좋아
점수 안높아진게 충격이라 왜 그런지 한번 살펴보았다
| Trace | A util | A secs (μs) | A Kops | B util | B secs (μs) | B Kops | B/A secs× |
| ----- | ------ | ----------- | ------- | ------ | ----------- | ------- | --------- |
| 0 | 89% | 91.000 | 62,571 | 91% | 813.000 | 7,004 | 8.93× |
| 1 | 92% | 52.112 | 112,220 | 91% | 524.000 | 11,160 | 10.06× |
| 2 | 94% | 128.000 | 51,938 | 96% | 1564.000 | 4,251 | 12.22× |
| 3 | 96% | 88.000 | 61,136 | 96% | 1576.000 | 3,414 | 17.91× |
| 4 | 66% | 65.221 | 220,787 | 66% | 52.276 | 275,462 | 0.80× |
| 5 | 88% | 266.000 | 18,045 | 90% | 1947.000 | 2,465 | 7.32× |
| 6 | 85% | 272.000 | 17,647 | 88% | 1837.000 | 2,613 | 6.75× |
| 7 | 55% | 652.000 | 18,405 | 55% | 5564.000 | 2,157 | 8.53× |
| 8 | 51% | 667.000 | 35,982 | 51% | 5111.000 | 4,696 | 7.66× |
| 9 | 33% | 11277.000 | 1,277 | 27% | 19045.000 | 756 | 1.69× |
| 10 | 30% | 147.000 | 97,966 | 43% | 339.000 | 42,481 | 2.31× |
| Total | 71% | 13706.000 | 8,199 | 72% | 38372.000 | 2,928 | 2.80× |
보아하니 속도가 월등히 높아졌음에도 동점인 걸 보니… 속도는 40점이 만점이란 걸 알 수 있다
여기서 더 점수를 높이려면 util을 높여야 한다는 거다
그래서 find_fit을 first fit에서 best fit으로 교체했다
static void *find_fit(size_t asize) {
for (void *bp = free_head; bp != NULL; bp = GET_SUCC(bp)) {
if (GET_SIZE(HDRP(bp)) >= asize) return bp;
}
return NULL;
}
🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽
전환
🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽
static void *find_fit(size_t asize) {
void *best = NULL;
size_t best_size = __SIZE_MAX__;
for (void *bp = free_head; bp != NULL; bp = GET_SUCC(bp)) {
size_t csize = GET_SIZE(HDRP(bp)); // 매 반복마다 갱신
if (csize < asize) continue;
// 완벽 적합 → 즉시 반환
if (csize == asize) return bp;
// 더 작은 후보면 갱신
if (csize < best_size) {
best = bp;
best_size = csize;
// 남는 조각이 분할 불가면 사실상 perfect fit로 보고 바로 선택
if (best_size - asize < MIN_BLOCK) return best;
}
}
return best; // 없으면 NULL
}
다행히도 효과가 있었다
Results for mm malloc:
trace valid util ops secs Kops
0 yes 99% 5694 0.000129 44208
1 yes 99% 5848 0.000147 39755
2 yes 99% 6648 0.000153 43338
3 yes 99% 5380 0.000122 44280
4 yes 66% 14400 0.000125115477
5 yes 96% 4800 0.003742 1283
6 yes 95% 4800 0.003105 1546
7 yes 55% 12000 0.009270 1295
8 yes 51% 24000 0.031829 754
9 yes 28% 14401 0.000177 81454
10 yes 35% 14401 0.000117122875
Total 75% 112372 0.048915 2297
Perf index = 45 (util) + 40 (thru) = 85/100
어제보다 2점 올랐다…
음… 7~10이 뭔지는 몰라도 저기서 유틸이 박살난다
진짜 뭐지?
왜 유틸 꼴아박는지 모르겠다…
청크 사이즈 줄이기 같은 간단한 거 테스트 해보며 원인을 찾아가야겠다
그전에
driver를 -V로 실행해 쬐금 더 자세히 디버그 가능한 걸 알게 되었다
0. Reading tracefile: amptjp-bal.rep
1. Reading tracefile: cccp-bal.rep
2. Reading tracefile: cp-decl-bal.rep
3. Reading tracefile: expr-bal.rep
4. Reading tracefile: coalescing-bal.rep
5. Reading tracefile: random-bal.rep
6. Reading tracefile: random2-bal.rep
7. Reading tracefile: binary-bal.rep
8. Reading tracefile: binary2-bal.rep
9. Reading tracefile: realloc-bal.rep
10. Reading tracefile: realloc2-bal.rep
대충 이런식인 거 같다 7번부터 문제가 생기니
7. Reading tracefile: binary-bal.rep
8. Reading tracefile: binary2-bal.rep
9. Reading tracefile: realloc-bal.rep
10. Reading tracefile: realloc2-bal.rep
여기에 있는 테스트 케이스들을 살펴봐야겠다
현재 realloc을 우측 확장과 병합으로만 구현했는데 좌측도 구현해야 할듯 싶다
으윽… 그거까진 싫은데…
// 좌측 확장
if (!GET_PREV_ALLOC(HDRP(ptr))) {
void *prev = PREV_BLKP(ptr);
if (!GET_ALLOC(HDRP(prev))) {
size_t psize = GET_SIZE(HDRP(prev));
if (psize + oldsize >= asize) {
UNLINK(prev);
size_t copysize = (size < payload) ? size : payload;
memmove(prev, ptr, copysize);
PUT(HDRP(prev), PACK(psize + oldsize, GET_PREV_ALLOC(HDRP(prev)) | FL_ALLOC));
split_tail(prev, asize);
return prev;
}
/* 우측도 확장 (양쪽 확장) */
if (!GET_ALLOC(HDRP(next))) {
size_t nsize = GET_SIZE(HDRP(next));
if (psize + oldsize + nsize >= asize) {
UNLINK(prev);
UNLINK(next);
size_t combined = psize + oldsize + nsize;
size_t copySize = (size < payload) ? size : payload;
memmove(prev, ptr, copySize);
PUT(HDRP(prev), PACK(combined, GET_PREV_ALLOC(HDRP(prev)) | FL_ALLOC));
split_tail(prev, asize);
return prev;
}
}
}
}
대충 좌측있는지 확인하고 좌측 블록 크기 합쳐서 원하는 사이즈보다 크면 진행하고 아니면 우측도 확인하는 방식이다
return할때 이전 블록 포인터 반환한다는 거에 유의하면 그리 어렵지는 않다
사실 어렵다
그리고 이렇게까지 한 결과…
1점 올랐다…
trace valid util ops secs Kops
0 yes 99% 5694 0.000138 41351
1 yes 99% 5848 0.000150 39013
2 yes 99% 6648 0.000217 30608
3 yes 99% 5380 0.000119 45363
4 yes 66% 14400 0.000105137667
5 yes 96% 4800 0.003092 1553
6 yes 95% 4800 0.002975 1614
7 yes 55% 12000 0.009536 1258
8 yes 51% 24000 0.032589 736
9 yes 41% 14401 0.000244 58924
10 yes 45% 14401 0.000141102280
Total 77% 112372 0.049304 2279
Perf index = 46 (util) + 40 (thru) = 86/100
그래도 28%, 35% 에서 41%, 45%가 되었는데 드라마틱하게 오르지는 않은 모양이다
흠… 더 뭐해야 될지 모르는데;;
지금 굳이 분리 접합 그런걸로 넘어갈 필요 없이 유틸을 더 높여야 될듯하다
그러다가 속도 딸리면 분리 접합으로 넘어가고
일단은 늘어나는 청크 사이즈부터 손좀 봐야겠다 싶다
어차피 지금은 무푸터 정책이니 굳이 푸터블록까지 걱정해줄 필요 없다
할당할때는 푸터 버리니까 말이다
WSIZE*2
더해주던 거 WSIZE
하나로 바꿨다
이로써 과하게 더해주던 블록을 조금 아꼈다…
이렇게 바이트 아끼다 부자 되게 생겼다
#define ALLOC_OVERHEAD WSIZE
static inline size_t req_asize(size_t size) {
size_t a = ALIGN(size + ALLOC_OVERHEAD); /* 헤더만 포함 */
if (a < MIN_BLOCK) a = MIN_BLOCK; /* 최소 자유블록 크기 보장 */
return a;
}
이렇게 새로 쓸거 만들어주고
void *mm_malloc(size_t size) {
if (size == 0) return NULL;
// size_t asize = MAX(MIN_BLOCK, ALIGN(size + OVERHEAD)); 이거에서
size_t asize = req_asize(size); // << 이걸로
...
}
void *mm_realloc(void *ptr, size_t size) {
...
size_t oldsize = GET_SIZE(HDRP(ptr));
// size_t payload = oldsize - OVERHEAD; OVERHEAD = 2*WSIZE
size_t oldpayload = oldsize - WSIZE; // WSIZE하나로 교체
// size_t asize = MAX(MIN_BLOCK, ALIGN(size + OVERHEAD)); 이거에서
size_t asize = req_asize(size); // << 이걸로
...
}
malloc하고 realloc에서 교체 해주었다
…
ㅅㅂ 1점도 안올랐다
티끌 모아봤자 티끌이다
청크사이즈 개선하러 가자
우선 realloc의 힙익스텐드를 개선했다
if (extend_heap((asize + WSIZE - 1) / WSIZE) != NULL)
이런식으로 그냥 asize
만큼 확장했는데 이를 해결하기 위해
size_t need = asize - oldsize;
if (extend_heap((need + WSIZE - 1) / WSIZE) != NULL)
need
변수를 도입해 확장하는 양을 좀 줄였다
으음… 이게 문제가 아니었는지 딱히 안올랐다
그래도 일단은 다 해볼 생각이다
그 다음에 malloc
에서 속도 희생하고 유틸을 높이기 위해
asize
가 청크사이즈보다 작다면 청크사이즈만큼 늘리던걸 무조건 asize
만큼 늘리게 바꿨다
extendsize = MAX(asize, CHUNKSIZE);
if ((bp = extend_heap(extendsize/WSIZE)) == NULL)
return NULL;
place(bp, asize);
return bp;
🔽🔽🔽🔽🔽🔽🔽🔽🔽
변경
🔽🔽🔽🔽🔽🔽🔽🔽🔽
extendsize = asize;
if ((bp = extend_heap((extendsize + WSIZE - 1)/WSIZE)) == NULL)
return NULL;
place(bp, asize);
return bp;
속도가 떨어졌지만 점수가 깍일 정도는 아니었고…
3점이나 올랐다!!!
trace 10에서 상당히 히트인걸 보니 realloc
잔뜩 했나 보다
Results for mm malloc:
trace valid util ops secs Kops
0 yes 99% 5694 0.000133 42941
1 yes 100% 5848 0.000141 41358
2 yes 99% 6648 0.000155 42890
3 yes 100% 5380 0.000112 48165
4 yes 66% 14400 0.000135106746
5 yes 96% 4800 0.002973 1615
6 yes 95% 4800 0.003240 1482
7 yes 55% 12000 0.008204 1463
8 yes 51% 24000 0.017505 1371
9 yes 45% 14401 0.000105137283
10 yes 87% 14401 0.000056258082
Total 81% 112372 0.032758 3430
Perf index = 49 (util) + 40 (thru) = 89/100
잘하면 90점 넘길 수 있겠다
util
을 어떻게든 끌어올려야겠다
지금 보니 4번도 util
이 영 시원찮다 병합의 효율을 올리면 realloc
이랑 다른 것도 오를 거 같으니 수정해보아야겠다
병합 case 4에서 푸터 prev_block말고 next_block을 가리키던 오류 하나 수정하고
mm_init에서 초기에 힙 영역 확장하는게 문제라며 제거하고 초기 할당할때 불러오게 바꿨다
그리 효과 있을지 모르곘다
…?
Results for mm malloc:
trace valid util ops secs Kops
0 yes 99% 5694 0.000129 44071
1 yes 100% 5848 0.000142 41329
2 yes 99% 6648 0.000167 39856
3 yes 100% 5380 0.000124 43387
4 yes 100% 14400 0.000088163080
5 yes 96% 4800 0.002960 1622
6 yes 95% 4800 0.003196 1502
7 yes 55% 12000 0.008483 1415
8 yes 51% 24000 0.032008 750
9 yes 100% 14401 0.000116124147
10 yes 87% 14401 0.000118121836
Total 89% 112372 0.047531 2364
Perf index = 54 (util) + 40 (thru) = 94/100
머임??????
점수 떡상했다 emoji
오류 수정때문에 많이 오른 건 아니고
mm_init에서 초기 청크사이즈 불러오는 거 제거했더니 util이 잔뜩 올랐다
현재 점수를 깍아먹던 realloc의 트레이스 경우
4095 → 4095 → free 둘 다 → 8190 라는 패턴이 반복된다
그리고 현재 이를
4095
요청 → asize = ALIGN(4095 + 4) = 4104
8190
요청 → asize = ALIGN(8190 + 4) = 8200
이렇게 처리하는데 초기힙을 CHUNKSIZE
로 받게 해놓아 4096B가 미리 있다는 거다
그러니 4104B가 4096B에 안들어가 추가 확장 일어나고 이에 따라 계속해서 4096 vs 4104가 엇갈리며 자투리(4096) 블록이 남는다
그 자투리로는 다음 4104B를 못 받으니 또 확장을 반복하게 되어 최종힙이 쓸데 없이 커지는 거였다…
trace 안뜯어 봤으면 ㄹㅇ 절대 몰랐을 건데
해결은 의외로 간단히 되었다
…아닌가?
그냥 오류 수정해서 그런건가?
솔직히 잘 모르겠다
이정도면 여기서 하루 시마이쳐도 나쁘지 않지만
이렇게 된 거 trace 10도 한번 알아보자
trace 10의 경우는 단순히 큰 블록만 붙이는게 아니라 강 약 강 약 섞어서 쬐깐이들을 던진다
그러면서 강 블록 해제하고 살짝 더 키운 거 던져서 제자리 할당 못하고 새로 확장하게 한다
이때문에 개같은 거 효율이 안나온다 강 뒤에 붙은 쬐깐이 떼주는 함수 만들어 쇼부 봐야한다
그래서 어캐함?