Bläddra i källkod

mm malloc v1 - 66

master
朱文韬 1 år sedan
förälder
incheckning
f8b538c213
16 ändrade filer med 112686 tillägg och 50 borttagningar
  1. +1
    -1
      labs/malloclab_lab/Makefile
  2. Binär
      labs/malloclab_lab/mdriver
  3. +205
    -49
      labs/malloclab_lab/mm.c
  4. Binär
      labs/malloclab_lab/mm.o
  5. +64
    -0
      labs/malloclab_lab/solve_note.md
  6. +5698
    -0
      labs/malloclab_lab/traces/amptjp-bal.rep
  7. +12004
    -0
      labs/malloclab_lab/traces/binary-bal.rep
  8. +24004
    -0
      labs/malloclab_lab/traces/binary2-bal.rep
  9. +5852
    -0
      labs/malloclab_lab/traces/cccp-bal.rep
  10. +14404
    -0
      labs/malloclab_lab/traces/coalescing-bal.rep
  11. +6652
    -0
      labs/malloclab_lab/traces/cp-decl-bal.rep
  12. +5384
    -0
      labs/malloclab_lab/traces/expr-bal.rep
  13. +4804
    -0
      labs/malloclab_lab/traces/random-bal.rep
  14. +4804
    -0
      labs/malloclab_lab/traces/random2-bal.rep
  15. +14405
    -0
      labs/malloclab_lab/traces/realloc-bal.rep
  16. +14405
    -0
      labs/malloclab_lab/traces/realloc2-bal.rep

+ 1
- 1
labs/malloclab_lab/Makefile Visa fil

@ -6,7 +6,7 @@ VERSION = 1
HANDINDIR = /afs/cs.cmu.edu/academic/class/15213-f01/malloclab/handin
CC = gcc
CFLAGS = -Wall -O2 -m32
CFLAGS = -Wall -Werror -O3 -g -DDRIVER -std=gnu99 -Wno-unused-function -Wno-unused-parameter -m32
OBJS = mdriver.o mm.o memlib.o fsecs.o fcyc.o clock.o ftimer.o

Binär
labs/malloclab_lab/mdriver Visa fil


+ 205
- 49
labs/malloclab_lab/mm.c Visa fil

@ -24,11 +24,11 @@
********************************************************/
team_t team = {
/* Team name */
"ateam",
"team",
/* First member's full name */
"Harry Bovik",
"GentleCold",
/* First member's email address */
"bovik@cs.cmu.edu",
"1952173800@qq.com",
/* Second member's full name (leave blank if none) */
"",
/* Second member's email address (leave blank if none) */
@ -37,74 +37,230 @@ team_t team = {
/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8
/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~0x7)
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~0x7)
// My define
#define WSIZE 4
#define DSIZE 8
#define FSIZE 16
#define CHUNK 1 << 10
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define PARSE(v) ((v) & ~0x7)
#define PACK(v, a) ((v) | (a))
#define HEAD(bp) ((byte *)(bp) - WSIZE)
#define FOOT(bp) ((byte *)(bp) + SIZE(bp))
#define SIZE(bp) (PARSE(GET(HEAD(bp))))
#define ALLOC(bp) (GET(HEAD(bp)) & 0x1)
#define GET(p) (*(word *)(p))
#define SET(p, v) (*(word *)(p) = (v))
#define NEXT(bp) (FOOT(bp) + DSIZE)
#define PREV(bp) ((byte *)(bp) - PARSE(GET((bp) - DSIZE)) - DSIZE)
typedef unsigned int word;
typedef char byte;
// mark the front and tail pos
void *front_p = NULL;
void *tail_p = NULL;
// My func
/**
* add a blank chunk and coalesce
* will update tail_p
* @param size align by 8, excluding head and foot
* @return new bp
*/
static void *_extend(size_t size);
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
/**
* coalesce blank chunk before and after bp
* @param bp loaded point
* @return bp after coalesce
*/
static void *_coalesce(void *bp);
static void *__coalesce_prev(void *bp);
static void *__coalesce_next(void *bp);
static void *__coalesce_all(void *bp);
/*
* mm_init - initialize the malloc package.
/**
* traverse and find first fit, then place in
* @param size align by 8, excluding head and foot
* @return
*/
int mm_init(void)
{
static void *_first_fit(size_t size);
/**
* allocate the block and cut sometimes
* @param size align by 8, excluding head and foot
*/
static void _place(void *ptr, size_t size);
// end
/**
* initialize the malloc package.
* get a new chunk, set front_p and tail_p
*/
int mm_init(void) {
if ((front_p = mem_sbrk(WSIZE)) == (void *) - 1) return -1; // blank
front_p += DSIZE; // first chunk
if (!_extend(CHUNK)) return -1;
return 0;
}
/*
* mm_malloc - Allocate a block by incrementing the brk pointer.
* Always allocate a block whose size is a multiple of the alignment.
/**
* find first fit or extend
*/
void *mm_malloc(size_t size)
{
int newsize = ALIGN(size + SIZE_T_SIZE);
void *p = mem_sbrk(newsize);
if (p == (void *)-1)
return NULL;
else {
*(size_t *)p = size;
return (void *)((char *)p + SIZE_T_SIZE);
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) {
return bp;
} else {
extend_size = adjust_size;
if (!ALLOC(tail_p)) {
extend_size -= (SIZE(tail_p) + DSIZE);
}
bp = _extend(MAX(extend_size, CHUNK));
if (bp == NULL) return bp;
_place(bp, adjust_size);
return bp;
}
}
/*
* mm_free - Freeing a block does nothing.
/**
* free a block and coalesce immediately
*/
void mm_free(void *ptr)
{
void mm_free(void *ptr) {
size_t size = SIZE(ptr);
SET(HEAD(ptr), PACK(size, 0));
SET(FOOT(ptr), PACK(size, 0));
_coalesce(ptr);
}
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
/**
* implemented simply in terms of mm_malloc and mm_free
* if size <= old_size, then cut instead of malloc and coalesce
* if the rest blank are enough for the size, then coalesce
* if too big, then cut again
*/
void *mm_realloc(void *ptr, size_t size)
{
void *oldptr = ptr;
void *newptr;
size_t copySize;
newptr = mm_malloc(size);
if (newptr == NULL)
return NULL;
copySize = *(size_t *)((char *)oldptr - SIZE_T_SIZE);
if (size < copySize)
copySize = size;
memcpy(newptr, oldptr, copySize);
mm_free(oldptr);
return newptr;
}
void *mm_realloc(void *ptr, size_t size) {
if (ptr == NULL) return mm_malloc(size);
if (size == 0) return NULL;
void *new_ptr;
size_t old_size = SIZE(ptr);
size_t adjust_size = ALIGN(size);
if (adjust_size <= old_size) {
if (old_size - adjust_size >= FSIZE) {
_place(ptr, adjust_size); // just cut
if (NEXT(ptr) != tail_p && !ALLOC(NEXT(NEXT(ptr)))) __coalesce_next(NEXT(ptr));
}
return ptr;
} else {
if (ptr != tail_p && !ALLOC(NEXT(ptr)) && SIZE(ptr) + SIZE(NEXT(ptr)) + DSIZE >= adjust_size) {
if (NEXT(ptr) == tail_p) tail_p = ptr;
size_t new_size = SIZE(ptr) + SIZE(NEXT(ptr)) + DSIZE;
SET(HEAD(ptr), PACK(new_size, 1));
SET(FOOT(ptr), PACK(new_size, 1));
if (SIZE(ptr) - adjust_size >= FSIZE) {
_place(ptr, adjust_size);
}
return ptr;
}
if ((new_ptr = mm_malloc(size)) == NULL) return NULL;
memcpy(new_ptr, ptr, old_size);
mm_free(ptr);
return new_ptr;
}
}
// my func
static void *_extend(size_t size) {
void *bp;
if ((bp = mem_sbrk(size + DSIZE)) == (void *) - 1) return NULL;
// init chunk
SET(bp, PACK(size, 0));
bp += WSIZE;
SET(FOOT(bp), PACK(size, 0));
// init mark point
tail_p = bp;
return _coalesce(bp);
}
static void *_coalesce(void *bp) {
// one chunk
if (bp == front_p && bp == tail_p) return bp;
if (bp == front_p || ALLOC(PREV(bp))) {
if (bp == tail_p || ALLOC(NEXT(bp))) return bp;
return __coalesce_next(bp);
} else if (bp == tail_p || ALLOC(NEXT(bp))) {
return __coalesce_prev(bp);
} else {
return __coalesce_all(bp);
}
}
static void *__coalesce_prev(void *bp) {
void *prev = PREV(bp);
size_t new_size = SIZE(prev) + SIZE(bp) + DSIZE;
SET(HEAD(prev), PACK(new_size, 0));
SET(FOOT(bp), PACK(new_size, 0));
if (bp == tail_p) tail_p = prev;
return prev;
}
static void *__coalesce_next(void *bp) {
void *next = NEXT(bp);
size_t new_size = SIZE(next) + SIZE(bp) + DSIZE;
SET(HEAD(bp), PACK(new_size, 0));
SET(FOOT(next), PACK(new_size, 0));
if (next == tail_p) tail_p = bp; // should also change
return bp;
}
static void *__coalesce_all(void *bp) {
void *prev = PREV(bp);
void *next = NEXT(bp);
size_t new_size = SIZE(prev) + SIZE(bp) + SIZE(next) + FSIZE;
SET(HEAD(prev), PACK(new_size, 0));
SET(FOOT(next), PACK(new_size, 0));
if (next == tail_p) tail_p = prev;
return prev;
}
static void *_first_fit(size_t size) {
void *bp = front_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);
}
return NULL;
}
static void _place(void *ptr, size_t size) {
size_t p_size = SIZE(ptr);
if (p_size - size >= FSIZE) {
SET(HEAD(ptr), PACK(size, 1));
SET(FOOT(ptr), PACK(size, 1));
// DSIZE adjust
size_t adjust_size = p_size - size - DSIZE;
SET(HEAD(NEXT(ptr)), PACK(adjust_size, 0));
SET(FOOT(NEXT(ptr)), PACK(adjust_size, 0));
if (ptr == tail_p) tail_p = NEXT(ptr);
} else {
SET(HEAD(ptr), PACK(p_size, 1));
SET(FOOT(ptr), PACK(p_size, 1));
}
}

Binär
labs/malloclab_lab/mm.o Visa fil


+ 64
- 0
labs/malloclab_lab/solve_note.md Visa fil

@ -0,0 +1,64 @@
## 关于示例代码的理解
#### 环境
* 从 `mem_init` 中可以看出整个分配器是在一大段已经分配好的连续的内存中进行的
* 同样每次 `mem_sbrk` 进行扩展时也是连续扩展,模拟堆的向上增长
#### 对齐
* 标准 `malloc` 也是八字节对齐,所以可以满足强制八字节对齐的要求
* 返回的内存应为有效载荷部分,如果每个块加上头部和脚部,为了满足对齐要求,须在开头空出四字节的位置
* 也意味着空闲块最小为八字节大小,有效载荷也应八字节对齐,已分配块最小十六字节
#### 测试
* handout 里的测试用例偏少,从网上找到了更为详尽的 `traces` 测试用例来测试
## version 1
#### 规则与注意
理解逻辑后,接下来将实现自己的版本
* 为方便理解,定义了两个类型别名
```c
typedef unsigned int word;
typedef char byte;
```
* 不同于示例代码用序言块和尾块标记,本人仅用两个指针标记头尾,来提高内存利用率
```c
// mark the front and tail pos
void *front_p = NULL;
void *tail_p = NULL;
```
* 但会增加代码的复杂度,需着重维护
* 同时还应注意若 `bp == front_p``PREV(bp)` 内的值无效,`tail_p` 同理
* 为保持一致性,向辅助函数内传入的 `size` 均应在传入之前对齐,均不包含头尾部大小
* 仅在内部碎片大于等于十六字节时才进行切割
* 其他部分与示例大同小异
#### bug 与 debug
* `#debug`对于 `segmentation fault` 使用 `gdb` 获取头尾块的 `size` 发现尾部异常值 `0xcdcdcd`,在代码中使用 `print` 跟踪 `trail_p` 变量,发现在`__coalesce_next`处没有及时更新
* `#bug1` 若记录的 `size` 是有效载荷的 `size`,合并和分割时应注意增减 `DSIZE`
* `#bug2` 每次合并都需要判断 `tail_p` 是否改变,特别是 `__coalesce_next` 的情况
#### 方法与得分
* 隐式空闲链表,首次适配,立即合并
```c
Results for mm malloc:
trace valid util ops secs Kops
0 yes 99% 5694 0.007579 751
1 yes 100% 5848 0.006639 881
2 yes 99% 6648 0.010560 630
3 yes 100% 5380 0.008016 671
4 yes 100% 14400 0.000102140762
5 yes 92% 4800 0.006677 719
6 yes 92% 4800 0.005988 802
7 yes 55% 12000 0.141468 85
8 yes 51% 24000 0.274197 88
9 yes 33% 14401 0.128358 112
10 yes 50% 14401 0.002138 6734
Total 79% 112372 0.591722 190
Perf index = 47 (util) + 13 (thru) = 60/100
```
## Version 1.1
#### 针对 `realloc` 的优化 v1
* 若 `new_size <= old_size` 则不分配而是切割
* 若下一块未分配且总和大于 `new_size` 则合并
* 若合并后内部碎片过大则仍需分割
* 提高六分,但判断过多,且考虑不全
#### 针对 `realloc` 的优化 v2
* 评估前后空闲块的总大小,若足够,则合并
* 合并不会破坏数据,合并后复制数据,再根据需要分割
***
2022.12.29 ~ 2022.12.30

+ 5698
- 0
labs/malloclab_lab/traces/amptjp-bal.rep
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 12004
- 0
labs/malloclab_lab/traces/binary-bal.rep
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 24004
- 0
labs/malloclab_lab/traces/binary2-bal.rep
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 5852
- 0
labs/malloclab_lab/traces/cccp-bal.rep
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 14404
- 0
labs/malloclab_lab/traces/coalescing-bal.rep
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 6652
- 0
labs/malloclab_lab/traces/cp-decl-bal.rep
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 5384
- 0
labs/malloclab_lab/traces/expr-bal.rep
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 4804
- 0
labs/malloclab_lab/traces/random-bal.rep
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 4804
- 0
labs/malloclab_lab/traces/random2-bal.rep
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 14405
- 0
labs/malloclab_lab/traces/realloc-bal.rep
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 14405
- 0
labs/malloclab_lab/traces/realloc2-bal.rep
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


Laddar…
Avbryt
Spara