CSAPP: Malloc lab

介绍

在该实验中,需要用C语言实现一个动态存储分配器(dynamic storage allocater)。需要实现malloc、free、realloc等功能。当然不仅要正确的实现相关功能也要满足速度效率等要求。

实验准备

  1. 实验材料:
    原始实验包github下载
    原始实验包中测试用的trace不存在,下面下载测试文件的链接:12 traces
    本博主的实现的最终版本mm.c源文件 93/100分

执行make命令时可能出现以下问题
fatal error sys/cdefs.h no such file or directory
致命错误: sys/cdefs.h:没有那个文件或目录
出现此错误是因为在64位Linux操作系统中打算编译出32位的程序,解决方案
如下: sudo apt-get install build-essential libc6-dev libc6-dev-i386

  1. 必要知识:
    《深入理解计算机系统》第二版第9章虚拟存储器的内容需要熟悉。特别是9.9节动态存储器分配中9.9.12节“综合:实现一个简单的分配器”
  2. 存储器实现的必要技术:

    • 针对空闲块的组织方法有以下三种:
      a.隐式空闲链表(implicit free list)
      b.显式空闲链表(explicit free list)
      c.分离空闲链表(segregated free list)

    • 查找空闲块的三个方法:
      a.首次适应(first fit)
      b.最佳适配(best fit)
      c.下一次适配(next fit)

  3. 实验小建议
    a.先最简单的开始实现,也即是书本上的范例隐式空闲链表的实现方法。然后一步步一次实现其他的方法
    以下是我依次实现的其他两个版本
    mm.c 隐式空闲链表+首次适配+原始realloc版
    mm.c 显示空闲链表+首次适配+原始realloc版
    mm.c 分离空闲链表+最佳适配+改进的realloc版

    b.最后的优化需要根据不同的trace进行分析优化

    c.需要用到gdb调试,修改Makefile文件,对于编译命令加入-g字段,并且删除-02优化字段,防止调试时出现怪异问题(i.e 调试时程序不是一行一行顺序 ,而是跳跃的)


最终版本实现的思路

  • 空闲块的组织方法-segregated free list
    segregated free list 中大小类的分类方法如下,并且将该list表放在heap的头部,通过序言块将它与数据隔离。在每一个大小类中,空闲块按照size由大到小排序。
PUT(heap_listp,0);              /*block size list<=32*/
PUT(heap_listp+(1*WSIZE),0);    /*block size list<=64*/
PUT(heap_listp+(2*WSIZE),0);    /*block size list<=128*/
PUT(heap_listp+(3*WSIZE),0);    /*block size list<=256*/
PUT(heap_listp+(4*WSIZE),0);    /*block size list<=512*/
PUT(heap_listp+(5*WSIZE),0);    /*block size list<=2048*/
PUT(heap_listp+(6*WSIZE),0);    /*block size list<=4096*/
PUT(heap_listp+(7*WSIZE),0);    /*block size list>4096*/
PUT(heap_listp+(8*WSIZE),0);    /* for alignment*/
PUT(heap_listp+(9*WSIZE),PACK(DSIZE,1));
PUT(heap_listp+(10*WSIZE),PACK(DSIZE,1));
PUT(heap_listp+(11*WSIZE),PACK(0,1));
  • 空闲块查找方法 - best fit
    因为同一大小类中空闲块由小到大排序,所以查找是第一个合适的就是最适配的

  • mm_realloc 改进
    对于请求的newsize>原始的oldsize这种情况,我们将运用类似coalesce中的方法,先去检查前后是否有空闲块,并是否满足前后空闲块和当前已分配的空闲块size相加大于newsize,如果是则合并,不需要再重新请求空闲块。如果不行,则需要重新mm_malloc一块新的空间

/*
 * mm_realloc 
 * 1. Given size is equal to 0 ,just free the given ptr
 * 2. Given ptr is equal to NULL ,just new malloc a space which size is given size
 * 
 * 3. oldsize is smaller than new size (asize),than call realloc_coalesce to coalesce the previous and next free block, 
 *    if realloc_coalesce success ,just move the payload into new address.
 *    if not success, mm_alloc a new space.
 *
 * 4.oldsize is bigger than new size (asize),just call realloc_place to change the size of ptr.
 */
void *mm_realloc(void *ptr, size_t size){
    size_t oldsize = GET_SIZE(HDRP(ptr));
    void *newptr;
    size_t asize;

    if(size == 0){
        mm_free(ptr);
        return 0;
    }

    if(ptr == NULL) return mm_malloc(size);

    /*compute the total size,which contanins header + footer + payload and fit the alignment requirement*/
    if(size <= DSIZE){
        asize = 2*(DSIZE);
    }else{
        asize = (DSIZE)*((size+(DSIZE)+(DSIZE-1)) / (DSIZE));
    }

    if(oldsize==asize) return ptr;

    if(oldsize
    {
        int isnextFree;
        char *bp = realloc_coalesce(ptr,asize,&isnextFree);
        if( isnextFree==1){ /*next block is free*/
            realloc_place(bp,asize);
            return bp;
        } else if(isnextFree ==0 && bp != ptr){ /*previous block is free, move the point to new address,and move the payload*/
            memcpy(bp, ptr, size);
            realloc_place(bp,asize);
            return bp;
        }else{
        /*realloc_coalesce is fail*/
            newptr = mm_malloc(size);
            memcpy(newptr, ptr, size);
            mm_free(ptr);
            return newptr;
        }
    }
    else
    {/*just change the size of ptr*/
        realloc_place(ptr,asize);
        return ptr;
    }
}

不同版本实验的结果

隐式空闲链表+首次适配+原始realloc版
Results for mm malloc:
trace  valid  util     ops      secs  Kops
 0       yes   99%    5694  0.013870   411
 1       yes   99%    5848  0.011893   492
 2       yes   99%    6648  0.019040   349
 3       yes  100%    5380  0.014521   371
 4       yes   66%   14400  0.000350 41190
 5       yes   92%    4800  0.013450   357
 6       yes   92%    4800  0.014184   338
 7       yes   55%   12000  0.212383    57
 8       yes   51%   24000  0.463620    52
 9       yes   27%   14401  0.103638   139
10       yes   34%   14401  0.003529  4081
Total          74%  112372  0.870479   129

Perf index = 44 (util) + 9 (thru) = 53/100

-------------------------------
显示空闲链表+首次适配+原始realloc版
-Results for mm malloc:
trace  valid  util     ops      secs  Kops
 0       yes   89%    5694  0.000546 10421
 1       yes   92%    5848  0.000463 12644
 2       yes   94%    6648  0.000734  9056
 3       yes   96%    5380  0.000506 10624
 4       yes   99%   14400  0.000477 30163
 5       yes   88%    4800  0.001101  4360
 6       yes   85%    4800  0.001271  3777
 7       yes   55%   12000  0.006821  1759
 8       yes   51%   24000  0.005335  4499
 9       yes   26%   14401  0.103928   139
10       yes   34%   14401  0.003624  3974
Total          74%  112372  0.124806   900

Perf index = 44 (util) + 40 (thru) = 84/100

-------------------------------
分离空闲链表+最佳适配+改进的realloc版
Results for mm malloc:
trace  valid  util     ops      secs  Kops
 0       yes   99%    5694  0.000553 10306
 1       yes   99%    5848  0.000567 10323
 2       yes   99%    6648  0.000568 11698
 3       yes  100%    5380  0.000437 12322
 4       yes   99%   14400  0.000600 23988
 5       yes   95%    4800  0.001740  2758
 6       yes   95%    4800  0.001609  2984
 7       yes   55%   12000  0.000865 13865
 8       yes   51%   24000  0.002205 10885
 9       yes   40%   14401  0.001070 13459
10       yes   45%   14401  0.000845 17053
Total          80%  112372  0.011058 10162

Perf index = 48 (util) + 40 (thru) = 88/100


-------------------------------
分离空闲链表+最佳适配+改进的realloc版+realloc_place针对最后两个测试数据改进
Results for mm malloc:
trace  valid  util     ops      secs  Kops
 0       yes   99%    5694  0.000435 13087
 1       yes   99%    5848  0.000438 13339
 2       yes   99%    6648  0.000753  8831
 3       yes  100%    5380  0.000666  8081
 4       yes   99%   14400  0.000738 19515
 5       yes   95%    4800  0.002220  2162
 6       yes   95%    4800  0.001841  2607
 7       yes   55%   12000  0.000882 13613
 8       yes   51%   24000  0.002261 10613
 9       yes   95%   14401  0.000576 25006
10       yes   76%   14401  0.000517 27839
Total          88%  112372  0.011327  9920

Perf index = 53 (util) + 40 (thru) = 93/100

你可能感兴趣的:(计算机体系结构)