Przeglądaj źródła

mm malloc v1.2 - 88

master
朱文韬 1 rok temu
rodzic
commit
fa1f4cae4a
4 zmienionych plików z 102 dodań i 7 usunięć
  1. BIN
      labs/malloclab_lab/mdriver
  2. +77
    -7
      labs/malloclab_lab/mm.c
  3. BIN
      labs/malloclab_lab/mm.o
  4. +25
    -0
      labs/malloclab_lab/solve_note.md

BIN
labs/malloclab_lab/mdriver Wyświetl plik


+ 77
- 7
labs/malloclab_lab/mm.c Wyświetl plik

@ -68,6 +68,8 @@ typedef char byte;
// mark the front and tail pos
void *front_p = NULL;
void *tail_p = NULL;
// used for next fit, updated by mm_init, mm_malloc, _coalesce
void *fitted_p = NULL;
// My func
/**
@ -90,12 +92,28 @@ static void *__coalesce_all(void *bp);
/**
* traverse and find first fit, then place in
* @deprecated too slow
* @param size align by 8, excluding head and foot
* @return
*/
static void *_first_fit(size_t size);
/**
* find next fit, then place in
* @param size align by 8, excluding head and foot
* @return
*/
static void *_next_fit(size_t size);
/**
* find next fit, then place in, if from beginning, use best fit
* @deprecated thru loss
* @param size align by 8, excluding head and foot
* @return
*/
static void *_next_best_fit(size_t size);
/**
* allocate the block and cut sometimes
* @param size align by 8, excluding head and foot
*/
@ -109,6 +127,7 @@ static void _place(void *ptr, size_t size);
int mm_init(void) {
if ((front_p = mem_sbrk(WSIZE)) == (void *) - 1) return -1; // blank
front_p += DSIZE; // first chunk
fitted_p = front_p; // init fitted_p
if (!_extend(CHUNK)) return -1;
return 0;
}
@ -120,7 +139,8 @@ void *mm_malloc(size_t size) {
size_t adjust_size = ALIGN(size);
size_t extend_size;
void *bp;
if ((bp = _first_fit(adjust_size)) != NULL) {
if ((bp = _next_fit(adjust_size)) != NULL) {
fitted_p = bp;
return bp;
} else {
extend_size = adjust_size;
@ -130,6 +150,7 @@ void *mm_malloc(size_t size) {
bp = _extend(MAX(extend_size, CHUNK));
if (bp == NULL) return bp;
_place(bp, adjust_size);
fitted_p = bp;
return bp;
}
}
@ -146,9 +167,7 @@ void mm_free(void *ptr) {
/**
* implemented simply in terms of mm_malloc and mm_free
* if size <= old_size, then return
* if the rest blank are enough for the size, then coalesce
* if too big, then cut again
* compare adjust_size and total_size step by step
*/
void *mm_realloc(void *ptr, size_t size) {
if (ptr == NULL) return mm_malloc(size);
@ -164,9 +183,9 @@ void *mm_realloc(void *ptr, size_t size) {
size_t next_size = (ptr != tail_p && !ALLOC(NEXT(ptr))) ? SIZE(NEXT(ptr)) + DSIZE : 0;
size_t total_size = old_size + next_size;
if (adjust_size <= total_size) {
new_ptr = __coalesce_next(ptr);
_place(new_ptr, adjust_size); // just cut
return new_ptr;
__coalesce_next(ptr);
_place(ptr, adjust_size); // just cut
return ptr;
}
size_t prev_size = (ptr != front_p && !ALLOC(PREV(ptr))) ? SIZE(PREV(ptr)) + DSIZE : 0;
total_size += prev_size;
@ -214,6 +233,7 @@ static void *__coalesce_prev(void *bp) {
SET(HEAD(prev), PACK(new_size, 0));
SET(FOOT(bp), PACK(new_size, 0));
if (bp == tail_p) tail_p = prev;
if (bp == fitted_p) fitted_p = prev;
return prev;
}
@ -223,6 +243,7 @@ static void *__coalesce_next(void *bp) {
SET(HEAD(bp), PACK(new_size, 0));
SET(FOOT(next), PACK(new_size, 0));
if (next == tail_p) tail_p = bp; // should also change
if (next == fitted_p) fitted_p = bp;
return bp;
}
@ -233,6 +254,7 @@ static void *__coalesce_all(void *bp) {
SET(HEAD(prev), PACK(new_size, 0));
SET(FOOT(next), PACK(new_size, 0));
if (next == tail_p) tail_p = prev;
if (next == fitted_p || bp == fitted_p) fitted_p = prev;
return prev;
}
@ -249,6 +271,54 @@ static void *_first_fit(size_t size) {
return NULL;
}
static void *_next_fit(size_t size) {
void *bp = fitted_p;
void *after_p = NEXT(tail_p);
while (bp != after_p) {
if (!ALLOC(bp) && SIZE(bp) >= size) {
_place(bp, size);
return bp;
}
bp = NEXT(bp);
}
bp = front_p;
while (bp != fitted_p) {
if (!ALLOC(bp) && SIZE(bp) >= size) {
_place(bp, size);
return bp;
}
bp = NEXT(bp);
}
return NULL;
}
static void *_next_best_fit(size_t size) {
void *bp = fitted_p;
void *after_p = NEXT(tail_p);
while (bp != after_p) {
if (!ALLOC(bp) && SIZE(bp) >= size) {
_place(bp, size);
return bp;
}
bp = NEXT(bp);
}
bp = front_p;
size_t min = 0;
void *min_p = NULL;
while (bp != fitted_p) {
if (!ALLOC(bp) && SIZE(bp) >= size) {
if (min_p == NULL || SIZE(bp) < min) {
min = SIZE(bp);
min_p = bp;
}
}
bp = NEXT(bp);
}
if (min_p == NULL) return NULL;
_place(min_p, size);
return min_p;
}
static void _place(void *ptr, size_t size) {
size_t p_size = SIZE(ptr);
if (p_size - size >= FSIZE) {

BIN
labs/malloclab_lab/mm.o Wyświetl plik


+ 25
- 0
labs/malloclab_lab/solve_note.md Wyświetl plik

@ -84,6 +84,31 @@ Total 84% 112372 0.483734 232
Perf index = 50 (util) + 15 (thru) = 66/100
```
## Version 1.2
#### 使用 `next fit`
* 因为大块的空闲块总是趋向于在后面,所以下一次适配不用从头遍历,可以大幅提高吞吐率
* 引入新的全局变量 `fitted_p` 并且需要在多处维护:初始化,分配,合并
#### 结合 `best fit`
* `next_fit` 会降低内存利用率,而 `best_fit` 会降低吞吐率,但我们可以进行一个折衷,即在 `fitted_p` 后部分首次适配,而在 `fitted_p` 前部分最佳适配
* 而最佳适配仅需找到满足要求的最小值即可
* 然而因为前面的内存碎片太多,测试下来内存利用率的确有所提高,但是吞吐率下降的却更多,所以最后还是选择了 `_next_fit`
#### 得分
```c
Results for mm malloc:
trace valid util ops secs Kops
0 yes 91% 5694 0.001803 3158
1 yes 92% 5848 0.001315 4446
2 yes 97% 6648 0.003706 1794
3 yes 97% 5380 0.003602 1494
4 yes 100% 14400 0.000085169213
5 yes 91% 4800 0.004207 1141
6 yes 90% 4800 0.003837 1251
7 yes 55% 12000 0.057487 209
8 yes 51% 24000 0.029497 814
9 yes 50% 14401 0.054370 265
10 yes 70% 14401 0.000116124684
Total 80% 112372 0.160025 702
Perf index = 48 (util) + 40 (thru) = 88/100
```
***
2022.12.29 ~ 2022.12.30

Ładowanie…
Anuluj
Zapisz