Malloc-lab是针对CSAPP中对应的第九章9.9部分的内容,在这个实验中,我们需要实现自己的动态内存申请器。具体的要求可以参考writeup。
lab的具体内容可以在官网中下载,所有的lab代码在GitHub上。
1. 书本代码
其实书本上已经实现了部分的代码,我们首先将书本的代码实现,看看分数是多少?有关分数的评定,下载的文件中并没有给到,大家也可以去traces中拿到相关trace文件,以作评分用。
/*
* mm-naive.c - The fastest, least memory-efficient malloc package.
*
* In this naive approach, a block is allocated by simply incrementing
* the brk pointer. A block is pure payload. There are no headers or
* footers. Blocks are never coalesced or reused. Realloc is
* implemented directly using mm_malloc and mm_free.
*
* NOTE TO STUDENTS: Replace this header comment with your own header
* comment that gives a high level description of your solution.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "mm.h"
#include "memlib.h"
/*********************************************************
* NOTE TO STUDENTS: Before you do anything else, please
* provide your team information in the following struct.
********************************************************/
team_t team = {
/* Team name */
"iguochan",
/* First member's full name */
"IguoChan",
/* First member's email address */
"iguochan@foxmail.com",
/* Second member's full name (leave blank if none) */
"",
/* Second member's email address (leave blank if none) */
""
};
/* 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 SIZE_T_SIZE (ALIGN(sizeof(size_t)))
/* Basic constants and macros */
#define WSIZE 4
#define DSIZE 8
#define CHUNKSIZE (1 << 12)
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#define PACK(size, alloc) ((size) | (alloc))
#define GET(p) (*(unsigned int *)(p))
#define PUT(p, val) (*(unsigned int *)(p) = (val))
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
#define HDRP(bp) ((char *)(bp) - WSIZE)
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE)))
#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE)))
static char *heap_listp;
static void *extend_heap(size_t words);
static void *coalesce(void *bp);
static void *first_fit(size_t asize);
static void place(void *bp, size_t asize);
/*
* mm_init - initialize the malloc package.
*/
int mm_init(void)
{
if ((heap_listp = mem_sbrk(4*WSIZE)) == (void*)-1)
return -1;
PUT(heap_listp, 0);
PUT(heap_listp + (WSIZE), PACK(DSIZE, 1));
PUT(heap_listp + (2 * WSIZE), PACK(DSIZE, 1));
PUT(heap_listp + (3 * WSIZE), PACK(0, 1));
heap_listp += (2 * WSIZE);
if (extend_heap(CHUNKSIZE/WSIZE) == NULL)
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.
*/
void *mm_malloc(size_t size)
{
size_t asize;
size_t extendsize;
char *bp;
if (size == 0) return NULL;
if (size <= DSIZE)
asize = 2 * DSIZE;
else
asize = DSIZE * ((size + (DSIZE) + (DSIZE-1)) / DSIZE);
if ((bp = first_fit(asize)) != NULL) {
place(bp, asize);
return bp;
}
/* No fit found. Get more memory and place the block */
extendsize = MAX(asize,CHUNKSIZE);
if ((bp = extend_heap(extendsize/WSIZE)) == NULL)
return NULL;
place(bp, asize);
return bp;
}
/*
* mm_free - Freeing a block does nothing.
*/
void mm_free(void *ptr)
{
if (ptr == NULL) {
return;
}
size_t size = GET_SIZE(HDRP(ptr));
PUT(HDRP(ptr), PACK(size, 0));
PUT(FTRP(ptr), PACK(size, 0));
coalesce(ptr);
}
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size)
{
if (ptr == NULL)
return mm_malloc(size);
if (size == 0) {
mm_free(ptr);
return NULL;
}
void *oldptr = ptr;
void *newptr;
size_t copySize;
newptr = mm_malloc(size);
if (newptr == NULL)
return NULL;
copySize = GET_SIZE(HDRP(newptr));
if (size < copySize)
copySize = size;
memcpy(newptr, oldptr, copySize);
mm_free(oldptr);
return newptr;
}
static void *extend_heap(size_t words)
{
char *bp;
size_t size;
size = (words % 2) ? (words+1) * WSIZE : words * WSIZE;
if ((long)(bp = mem_sbrk(size)) == -1)
return NULL;
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1));
return coalesce(bp);
}
static void *coalesce(void *bp)
{
size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
size_t size = GET_SIZE(HDRP(bp));
if (prev_alloc && next_alloc) { /* Case 1 */
/* Do nothing */
} else if (prev_alloc && !next_alloc) { /* Case 2 */
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
} else if (!prev_alloc && next_alloc) { /* Case 3 */
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
bp = PREV_BLKP(bp);
} else { /* Case 4 */
size += GET_SIZE(HDRP(NEXT_BLKP(bp))) + GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
return bp;
}
static void *first_fit(size_t asize)
{
void *bp;
for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
if (!GET_ALLOC(HDRP(bp)) && (asize <= GET_SIZE(HDRP(bp))))
return bp;
}
return NULL;
}
static void place(void *bp, size_t asize)
{
size_t size = GET_SIZE(HDRP(bp));
if ((size - asize) >= (2*DSIZE)) {
PUT(HDRP(bp), PACK(asize,1));
PUT(FTRP(bp), PACK(asize,1));
bp = NEXT_BLKP(bp);
PUT(HDRP(bp), PACK(size - asize,0));
PUT(FTRP(bp), PACK(size - asize,0));
} else {
PUT(HDRP(bp), PACK(size,1));
PUT(FTRP(bp), PACK(size,1));
}
}
分数如下:
$ ./mdriver -t ./traces -V
Team Name:iguochan
Member 1 :IguoChan:iguochan@foxmail.com
Using default tracefiles in ./traces/
Measuring performance with gettimeofday().
...
Results for mm malloc:
trace valid util ops secs Kops
0 yes 99% 5694 0.009994 570
1 yes 99% 5848 0.008913 656
2 yes 99% 6648 0.013963 476
3 yes 100% 5380 0.011272 477
4 yes 66% 14400 0.000108133705
5 yes 92% 4800 0.010015 479
6 yes 92% 4800 0.009609 500
7 yes 55% 12000 0.171066 70
8 yes 51% 24000 0.322512 74
9 yes 27% 14401 0.072254 199
10 yes 34% 14401 0.003717 3874
Total 74% 112372 0.633421 177
Perf index = 44 (util) + 12 (thru) = 56/100
2. 用next_fit代替first_fit
我们用pre_listp指针指向上次分配的点,这样就不用每次从头去找空闲块了,整体代码如下:
/*
* mm-naive.c - The fastest, least memory-efficient malloc package.
*
* In this naive approach, a block is allocated by simply incrementing
* the brk pointer. A block is pure payload. There are no headers or
* footers. Blocks are never coalesced or reused. Realloc is
* implemented directly using mm_malloc and mm_free.
*
* NOTE TO STUDENTS: Replace this header comment with your own header
* comment that gives a high level description of your solution.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "mm.h"
#include "memlib.h"
/*********************************************************
* NOTE TO STUDENTS: Before you do anything else, please
* provide your team information in the following struct.
********************************************************/
team_t team = {
/* Team name */
"iguochan",
/* First member's full name */
"IguoChan",
/* First member's email address */
"iguochan@foxmail.com",
/* Second member's full name (leave blank if none) */
"",
/* Second member's email address (leave blank if none) */
""
};
/* 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 SIZE_T_SIZE (ALIGN(sizeof(size_t)))
/* Basic constants and macros */
#define WSIZE 4
#define DSIZE 8
#define CHUNKSIZE (1 << 12)
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#define PACK(size, alloc) ((size) | (alloc))
#define GET(p) (*(unsigned int *)(p))
#define PUT(p, val) (*(unsigned int *)(p) = (val))
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
#define HDRP(bp) ((char *)(bp) - WSIZE)
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE)))
#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE)))
static char *heap_listp;
static char *pre_listp;
static void *extend_heap(size_t words);
static void *coalesce(void *bp);
static void *first_fit(size_t asize);
static void *next_fit(size_t asize);
static void place(void *bp, size_t asize);
/*
* mm_init - initialize the malloc package.
*/
int mm_init(void)
{
if ((heap_listp = mem_sbrk(4*WSIZE)) == (void*)-1)
return -1;
PUT(heap_listp, 0);
PUT(heap_listp + (WSIZE), PACK(DSIZE, 1));
PUT(heap_listp + (2 * WSIZE), PACK(DSIZE, 1));
PUT(heap_listp + (3 * WSIZE), PACK(0, 1));
heap_listp += (2 * WSIZE);
pre_listp = heap_listp;
if (extend_heap(CHUNKSIZE/WSIZE) == NULL)
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.
*/
void *mm_malloc(size_t size)
{
size_t asize;
size_t extendsize;
char *bp;
if (size == 0) return NULL;
if (size <= DSIZE)
asize = 2 * DSIZE;
else
asize = DSIZE * ((size + (DSIZE) + (DSIZE-1)) / DSIZE);
if ((bp = next_fit(asize)) != NULL) {
place(bp, asize);
return bp;
}
/* No fit found. Get more memory and place the block */
extendsize = MAX(asize,CHUNKSIZE);
if ((bp = extend_heap(extendsize/WSIZE)) == NULL)
return NULL;
place(bp, asize);
return bp;
}
/*
* mm_free - Freeing a block does nothing.
*/
void mm_free(void *ptr)
{
if (ptr == NULL) {
return;
}
size_t size = GET_SIZE(HDRP(ptr));
PUT(HDRP(ptr), PACK(size, 0));
PUT(FTRP(ptr), PACK(size, 0));
coalesce(ptr);
}
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size)
{
if (ptr == NULL)
return mm_malloc(size);
if (size == 0) {
mm_free(ptr);
return NULL;
}
void *oldptr = ptr;
void *newptr;
size_t copySize;
newptr = mm_malloc(size);
if (newptr == NULL)
return NULL;
copySize = GET_SIZE(HDRP(newptr));
if (size < copySize)
copySize = size;
memcpy(newptr, oldptr, copySize);
mm_free(oldptr);
return newptr;
}
static void *extend_heap(size_t words)
{
char *bp;
size_t size;
size = (words % 2) ? (words+1) * WSIZE : words * WSIZE;
if ((long)(bp = mem_sbrk(size)) == -1)
return NULL;
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1));
return coalesce(bp);
}
static void *coalesce(void *bp)
{
size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
size_t size = GET_SIZE(HDRP(bp));
if (prev_alloc && next_alloc) { /* Case 1 */
/* Do nothing */
} else if (prev_alloc && !next_alloc) { /* Case 2 */
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
} else if (!prev_alloc && next_alloc) { /* Case 3 */
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
bp = PREV_BLKP(bp);
} else { /* Case 4 */
size += GET_SIZE(HDRP(NEXT_BLKP(bp))) + GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
pre_listp = bp;
return bp;
}
static void *next_fit(size_t asize)
{
void *bp;
for (bp = pre_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
if (!GET_ALLOC(HDRP(bp)) && (asize <= GET_SIZE(HDRP(bp)))) {
pre_listp = bp;
return bp;
}
}
for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
if (!GET_ALLOC(HDRP(bp)) && (asize <= GET_SIZE(HDRP(bp)))) {
pre_listp = bp;
return bp;
}
}
return NULL;
}
static void place(void *bp, size_t asize)
{
size_t size = GET_SIZE(HDRP(bp));
if ((size - asize) >= (2*DSIZE)) {
PUT(HDRP(bp), PACK(asize,1));
PUT(FTRP(bp), PACK(asize,1));
bp = NEXT_BLKP(bp);
PUT(HDRP(bp), PACK(size - asize,0));
PUT(FTRP(bp), PACK(size - asize,0));
} else {
PUT(HDRP(bp), PACK(size,1));
PUT(FTRP(bp), PACK(size,1));
}
pre_listp = bp;
}
分数如下,一下子提高到了83分。
$ ./mdriver -t ./traces -V
Team Name:iguochan
Member 1 :IguoChan:iguochan@foxmail.com
Using default tracefiles in ./traces/
Measuring performance with gettimeofday().
...
Results for mm malloc:
trace valid util ops secs Kops
0 yes 90% 5694 0.003638 1565
1 yes 93% 5848 0.002041 2865
2 yes 94% 6648 0.004940 1346
3 yes 96% 5380 0.005217 1031
4 yes 66% 14400 0.000108133581
5 yes 89% 4800 0.007406 648
6 yes 87% 4800 0.007437 645
7 yes 55% 12000 0.018366 653
8 yes 51% 24000 0.011100 2162
9 yes 26% 14401 0.072281 199
10 yes 34% 14401 0.003841 3749
Total 71% 112372 0.136373 824
Perf index = 43 (util) + 40 (thru) = 83/100
3. 分离的空闲链表
要想继续提高分配器的性能,需要用到课本内容9.9.13-9.9.14的知识。我们需要构建一个分离空闲链表,具体参考的是CS:APP3e 深入理解计算机系统_3e MallocLab实验。具体代码如下:
/*
* mm-naive.c - The fastest, least memory-efficient malloc package.
*
* In this naive approach, a block is allocated by simply incrementing
* the brk pointer. A block is pure payload. There are no headers or
* footers. Blocks are never coalesced or reused. Realloc is
* implemented directly using mm_malloc and mm_free.
*
* NOTE TO STUDENTS: Replace this header comment with your own header
* comment that gives a high level description of your solution.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "mm.h"
#include "memlib.h"
/*********************************************************
* NOTE TO STUDENTS: Before you do anything else, please
* provide your team information in the following struct.
********************************************************/
team_t team = {
/* Team name */
"iguochan",
/* First member's full name */
"IguoChan",
/* First member's email address */
"iguochan@foxmail.com",
/* Second member's full name (leave blank if none) */
"",
/* Second member's email address (leave blank if none) */
""
};
/* 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)) / (ALIGNMENT)) * (ALIGNMENT))
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
/* Basic constants and macros */
#define WSIZE 4
#define DSIZE 8
#define CHUNKSIZE (1 << 12)
#define INITCHUNKSIZE (1 << 6)
#define LISTMAX 16
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#define PACK(size, alloc) ((size) | (alloc))
#define GET(p) (*(unsigned int *)(p))
#define PUT(p, val) (*(unsigned int *)(p) = (val))
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
#define HDRP(bp) ((char *)(bp) - WSIZE)
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE)))
#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE)))
#define PRED_PTR(bp) ((char *)(bp))
#define SUCC_PTR(bp) ((char *)(bp) + WSIZE)
#define PRED(bp) (*(char **)(bp))
#define SUCC(bp) (*(char **)(SUCC_PTR(bp)))
#define SET_PTR(p, bp) ((*(unsigned int *)(p) = (unsigned int)(bp)))
void *segregated_free_lists[LISTMAX];
static void *extend_heap(size_t words);
static void *coalesce(void *bp);
static void place(void *bp, size_t asize);
static void insert_node(void *bp, size_t size);
static void delete_node(void *bp);
/*
* mm_init - initialize the malloc package.
*/
int mm_init(void)
{
int listnumber;
char *heap;
for (listnumber = 0; listnumber < LISTMAX; listnumber++) {
segregated_free_lists[listnumber] = NULL;
}
if ((heap = mem_sbrk(4*WSIZE)) == (void*)-1)
return -1;
PUT(heap, 0);
PUT(heap + (WSIZE), PACK(DSIZE, 1));
PUT(heap + (2 * WSIZE), PACK(DSIZE, 1));
PUT(heap + (3 * WSIZE), PACK(0, 1));
if (extend_heap(INITCHUNKSIZE) == NULL)
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.
*/
void *mm_malloc(size_t size)
{
size_t asize;
size_t extendsize;
char *bp = NULL;
int listnumber = 0;
size_t searchsize = size;
if (size == 0) return NULL;
if (size <= DSIZE)
asize = 2 * DSIZE;
else
asize = DSIZE * ((size + (DSIZE) + (DSIZE-1)) / DSIZE);
while (listnumber < LISTMAX)
{
/* 寻找对应链 */
if (((searchsize <= 1) && (segregated_free_lists[listnumber] != NULL)))
{
bp = segregated_free_lists[listnumber];
/* 在该链寻找大小合适的free块 */
while ((bp != NULL) && ((asize > GET_SIZE(HDRP(bp)))))
{
bp = PRED(bp);
}
/* 找到对应的free块 */
if (bp != NULL)
break;
}
searchsize >>= 1;
listnumber++;
}
/* No fit found. Get more memory and place the block */
if (bp == NULL) {
extendsize = MAX(asize,CHUNKSIZE);
if ((bp = extend_heap(extendsize)) == NULL)
return NULL;
}
place(bp, asize);
return bp;
}
/*
* mm_free - Freeing a block does nothing.
*/
void mm_free(void *bp)
{
if (bp == NULL) {
return;
}
size_t size = GET_SIZE(HDRP(bp));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
insert_node(bp, size);
coalesce(bp);
}
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size)
{
void *new_block = ptr;
int remainder;
if (size == 0)
return NULL;
/* 内存对齐 */
if (size <= DSIZE)
{
size = 2 * DSIZE;
}
else
{
size = ALIGN(size + DSIZE);
}
/* 如果size小于原来块的大小,直接返回原来的块 */
if ((remainder = GET_SIZE(HDRP(ptr)) - size) >= 0)
{
return ptr;
}
/* 否则先检查地址连续下一个块是否为free块或者该块是堆的结束块,因为我们要尽可能利用相邻的free块,以此减小“external fragmentation” */
else if (!GET_ALLOC(HDRP(NEXT_BLKP(ptr))) || !GET_SIZE(HDRP(NEXT_BLKP(ptr))))
{
/* 即使加上后面连续地址上的free块空间也不够,需要扩展块 */
if ((remainder = GET_SIZE(HDRP(ptr)) + GET_SIZE(HDRP(NEXT_BLKP(ptr))) - size) < 0)
{
if (extend_heap(MAX(-remainder, CHUNKSIZE)) == NULL)
return NULL;
remainder += MAX(-remainder, CHUNKSIZE);
}
/* 删除刚刚利用的free块并设置新块的头尾 */
delete_node(NEXT_BLKP(ptr));
PUT(HDRP(ptr), PACK(size + remainder, 1));
PUT(FTRP(ptr), PACK(size + remainder, 1));
}
/* 没有可以利用的连续free块,而且size大于原来的块,这时只能申请新的不连续的free块、复制原块内容、释放原块 */
else
{
new_block = mm_malloc(size);
memcpy(new_block, ptr, GET_SIZE(HDRP(ptr)));
mm_free(ptr);
}
return new_block;
}
static void *extend_heap(size_t words)
{
char *bp;
size_t size;
// size = (words % 2) ? (words+1) * WSIZE : words * WSIZE;
size = ALIGN(words);
if ((long)(bp = mem_sbrk(size)) == -1)
return NULL;
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1));
insert_node(bp, size);
return coalesce(bp);
}
static void *coalesce(void *bp)
{
size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
size_t size = GET_SIZE(HDRP(bp));
if (prev_alloc && next_alloc) { /* Case 1 */
/* Do nothing */
return bp;
} else if (prev_alloc && !next_alloc) { /* Case 2 */
delete_node(bp);
delete_node(NEXT_BLKP(bp));
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
} else if (!prev_alloc && next_alloc) { /* Case 3 */
delete_node(bp);
delete_node(PREV_BLKP(bp));
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
bp = PREV_BLKP(bp);
} else { /* Case 4 */
delete_node(bp);
delete_node(PREV_BLKP(bp));
delete_node(NEXT_BLKP(bp));
size += GET_SIZE(HDRP(NEXT_BLKP(bp))) + GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
insert_node(bp, size);
return bp;
}
static void place(void *bp, size_t asize)
{
size_t size = GET_SIZE(HDRP(bp));
delete_node(bp);
if ((size - asize) >= (2*DSIZE)) {
PUT(HDRP(bp), PACK(asize,1));
PUT(FTRP(bp), PACK(asize,1));
bp = NEXT_BLKP(bp);
PUT(HDRP(bp), PACK(size - asize,0));
PUT(FTRP(bp), PACK(size - asize,0));
insert_node(bp, size-asize);
} else {
PUT(HDRP(bp), PACK(size,1));
PUT(FTRP(bp), PACK(size,1));
}
}
/* listnumber和search_size的对应
| listnumber | search_size |
| 0 | 1 |
| 1 | 2-3 |
| 2 | 4-7 |
| 3 | 8-15 |
| 4 | 16-31 |
| 5 | 32-63 |
| 6 | 64-127 |
| 7 | 128-255 |
| 8 | 256-511 |
| 9 | 512-1023 |
| 10 | 1024-2047 |
| 11 | 2048-4095 |
| 12 | 4096-2^13-1 |
| 13 | 2^13-2^14-1 |
| 14 | 2^14-2^15-1 |
| 15 | 2^15-2^16-1 |
*/
static void insert_node(void *bp, size_t size) {
int listnumber = 0;
size_t search_size = size;
void *search_ptr = NULL;
void *insert_ptr = NULL;
/* 通过块的大小找到对应的链 */
while (listnumber < LISTMAX - 1 && search_size > 1) {
search_size >>= 1;
listnumber++;
}
/* 找到对应的链后,在该链中继续寻找对应的插入位置,以此保持链中块由大到小的特性
segregated_free_lists存储的是链表尾部的指针 */
search_ptr = segregated_free_lists[listnumber];
while (search_ptr != NULL && size > GET_SIZE(HDRP(search_ptr))) {
insert_ptr = search_ptr;
search_ptr = PRED(search_ptr);
}
if (search_ptr != NULL) {
/* 1. ...->search->bp->insert->... 在中间插入*/
if (insert_ptr != NULL)
{
SET_PTR(PRED_PTR(bp), search_ptr);
SET_PTR(SUCC_PTR(search_ptr), bp);
SET_PTR(SUCC_PTR(bp), insert_ptr);
SET_PTR(PRED_PTR(insert_ptr), bp);
}
/* 2. ...->search->bp->NULL 在结尾插入*/
/* 这种情形只能出现在没有进第二个while循环,也就是首次即不满足size > GET_SIZE(HDRP(search_ptr)),直接插在最后,更新segregated_free_lists */
else
{
SET_PTR(PRED_PTR(bp), search_ptr);
SET_PTR(SUCC_PTR(search_ptr), bp);
SET_PTR(SUCC_PTR(bp), NULL);
segregated_free_lists[listnumber] = bp;
}
} else {
/* 3. [listnumber]->bp->insert->... 在开头插入,但是后面有插入的 */
if (insert_ptr != NULL) {
SET_PTR(PRED_PTR(bp), NULL);
SET_PTR(SUCC_PTR(bp), insert_ptr);
SET_PTR(PRED_PTR(insert_ptr), bp);
}
/* 4. [listnumber]->bp->NULL 该链表为空,首次插入,需更新segregated_free_lists */
else
{
SET_PTR(PRED_PTR(bp), NULL);
SET_PTR(SUCC_PTR(bp), NULL);
segregated_free_lists[listnumber] = bp;
}
}
}
static void delete_node(void *bp)
{
int listnumber = 0;
size_t size = GET_SIZE(HDRP(bp));
/* 通过块的大小找到对应的链 */
while ((listnumber < LISTMAX - 1) && (size > 1))
{
size >>= 1;
listnumber++;
}
/* 通过块的大小找到对应的链 */
if (PRED(bp) != NULL) {
/* 1. ...->bp->... 在链表中间 */
if (SUCC(bp) != NULL)
{
SET_PTR(SUCC_PTR(PRED(bp)), SUCC(bp));
SET_PTR(PRED_PTR(SUCC(bp)), PRED(bp));
}
/* 2. ...->bp->NULL 在链表末尾 */
else
{
SET_PTR(SUCC_PTR(PRED(bp)), NULL);
segregated_free_lists[listnumber] = PRED(bp);
}
} else {
/* 3. ...->bp->... 在链表头,但是后续有链表 */
if (SUCC(bp) != NULL)
{
SET_PTR(PRED_PTR(SUCC(bp)), NULL);
}
/* 4. ...->bp->NULL 在链表头,且是唯一元素 */
else
{
segregated_free_lists[listnumber] = NULL;
}
}
}
跑分如下:
$$ ./mdriver -t traces -V
Team Name:iguochan
Member 1 :IguoChan:iguochan@foxmail.com
Using default tracefiles in traces/
Measuring performance with gettimeofday().
...
Results for mm malloc:
trace valid util ops secs Kops
0 yes 99% 5694 0.000336 16967
1 yes 99% 5848 0.000383 15277
2 yes 100% 6648 0.000959 6930
3 yes 100% 5380 0.000316 17025
4 yes 99% 14400 0.000678 21226
5 yes 96% 4800 0.001296 3704
6 yes 96% 4800 0.001011 4749
7 yes 55% 12000 0.000445 26966
8 yes 51% 24000 0.001557 15410
9 yes 99% 14401 0.000244 59142
10 yes 86% 14401 0.000226 63721
Total 89% 112372 0.007451 15082
Perf index = 53 (util) + 40 (thru) = 93/100