优化我的 malloc 函数的吞吐量

问题描述 投票:0回答:1

我有自己的 malloc 函数,带有显式的空闲列表来管理堆中的空间。空间使用的监管几乎完美,但我的吞吐量非常慢,我能对此做些什么吗?这已经是第一次适合(后进先出),其他任何东西在我耳中听起来都不会更快。

该内存分配器实现了显式空闲列表以实现高效的内存管理。 分配器使用堆空间进行内存分配。堆上的每个块要么被分配 用于管理未使用空间的使用或空闲列表的一部分。

区块结构: 每个块,无论是分配的还是空闲的,都包括页眉和页脚。页眉和页脚 每个都包含一个块大小指示符和一个分配位(0 表示空闲,1 表示已分配),其中 最小块大小为 16 字节(其中 8 字节用于有效负载,每个 4 字节用于传输) 页眉和页脚)。

在显式空闲列表中,空闲块还包含指向下一个和上一个空闲的指针 其有效负载空间内的块。这有利于有效地遍历和操纵自由 块。此外,我们还实现了序言和尾声块来处理免费的边缘情况 列表管理。

#define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~0x7)
#define MAX(x, y) ((x) > (y)? (x) : (y))
#define PACK(size, alloc) ((size) | (alloc))
#define GET(p)        (*(size_t *)(p))
#define PUT(p, val)   (*(size_t *)(p) = (val))
#define GET_SIZE(p)  (GET(p) & ~0x1)
#define GET_ALLOC(p) (GET(p) & 0x1)
#define HDRP(bp)     ((void *)(bp) - WSIZE)
#define FTRP(bp)     ((void *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)

#define NEXT_BLKP(bp) ((void *)(bp) + GET_SIZE(HDRP(bp)))
#define PREV_BLKP(bp) ((void *)(bp) - GET_SIZE(HDRP(bp) - WSIZE))
#define NEXT_FREE(bp)(*(void **)(bp))
#define PREV_FREE(bp)(*(void **)(bp + WSIZE))




static char *heap_list = 0;
static char *free_list = 0;

int mm_init(void)
{
    
    /* Create empty Heap */
    if ((heap_list = mem_sbrk(INITSIZE + MINBLOCKSIZE)) == (void *)-1)
        return -1;
    
    PUT(heap_list,              PACK(MINBLOCKSIZE, 1)); //  Prologue
    PUT(heap_list + (1*WSIZE),  PACK(MINBLOCKSIZE, 0)); //  Free block Header
    PUT(heap_list + (2*WSIZE),  PACK(0, 0));            //  Pointer to next free (space)
    PUT(heap_list + (3*WSIZE),  PACK(0, 0));            //  Pointer to previous free (space)
    PUT(heap_list + (4*WSIZE),  PACK(MINBLOCKSIZE, 0));  //  Free block footer
    PUT(heap_list + (5*WSIZE),  PACK(0, 1));            //  Epilogue
    free_list   =   heap_list + (WSIZE);
    
    

    
    
    return 0;

}


void *mm_malloc(size_t size)
{
    

    size_t asize ;
    
    void *bp;

    // Ignore useless allocation
    if(size == 0) 
    {
        return 0;
    }

    // Adjust the blocksize to include header and footer
    if(size <= DSIZE)
        asize = MINBLOCKSIZE;
    else
        // Align the size and add space for the header and footer
        asize = ALIGN(size) + DSIZE;
    
    // Search the free list for a fit, if found, place it.
    if ((bp = find_fit(asize)) != NULL)
    {

        place(bp, asize);
        return bp;
    }


    /* If there is no free space anymore, extend the Heap and then place it */
    
    if((bp = extend_heap(asize/WSIZE)) == NULL)
    {

        return NULL;

    }

    place(bp, asize);

    return bp;


}

/*
 * mm_free - Freeing a block does nothing.
 */
void mm_free(void *bp)
{

    size_t size = GET_SIZE(HDRP(bp));
    PUT(HDRP(bp), PACK(size, 0));
    PUT(FTRP(bp), PACK(size, 0));
    coalesce(bp);
}

/*
 * mm_realloc - Implemented simply in terms of mm_malloc and mm_free
 */
void *mm_realloc(void *ptr, size_t size)
{
    /*
     * ATTENTION: You do not need to implement realloc for this assignment
     */

    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;
}

// Helper functions


/* Function to extend the size of the heap */

static void *extend_heap (size_t words)
{


    char *bp;
    size_t size;
    
    /* Allocate an even number of words to maintain alignment */
    
    size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;

    if ((bp = mem_sbrk(size)) == -1 ) 
    {   

        return NULL;
    }
    
    /* Initialize free block header / footer and the epilogue header */
    PUT(HDRP(bp), PACK(size, 0));   //Free block header
    PUT(FTRP(bp), PACK(size, 0));   //Free block footer
    PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1));   //New Epiloge Header
    
    /* Coalesce if the previous block was free */
    return coalesce(bp);
}


static void *coalesce(void *bp)
{


    size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)))||PREV_BLKP(bp) == bp;
    size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
    size_t size = GET_SIZE(HDRP(bp));         

    
    /* Case1 : The previos and the next block are both allocated*/
    if ( prev_alloc && next_alloc )
    {

        PREV_FREE(free_list) = bp;
        NEXT_FREE(bp) = free_list;
        PREV_FREE(bp) = NULL;
        free_list = bp;

        return bp; 
    }

    /* Case2 : The previos block is allocates and the next block is free */
    else if ( prev_alloc && !next_alloc) 
    {

        size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
        remove_freeblock(NEXT_BLKP(bp));
        PUT(HDRP(bp), PACK(size, 0));
        PUT(FTRP(bp), PACK(size, 0));
    }

    /* The previos block is free and the next block is allocated */
    else if (!prev_alloc && next_alloc )
    {
        
        
        size += GET_SIZE(HDRP(PREV_BLKP(bp)));
        


        PUT(FTRP(bp), PACK(size, 0));
        PUT(HDRP(PREV_BLKP(bp)), PACK(size,0));
        bp = PREV_BLKP(bp);
        remove_freeblock(bp);
    }

    /* The previos and the next block are both free */
    else if (!prev_alloc && !next_alloc)
    {
        size += GET_SIZE(HDRP(PREV_BLKP(bp))) +
        GET_SIZE(FTRP(NEXT_BLKP(bp)));
        remove_freeblock(PREV_BLKP(bp));
        remove_freeblock(NEXT_BLKP(bp));
        PUT(HDRP(PREV_BLKP(bp)), PACK(size,0));
        PUT(FTRP(NEXT_BLKP(bp)), PACK(size,0));
        bp = PREV_BLKP(bp);
    }
   

    PREV_FREE(free_list) = bp;
    NEXT_FREE(bp) = free_list;
    PREV_FREE(bp) = NULL;
    free_list = bp;

    return bp;
}



static void *find_fit(size_t asize)
{
    

    // Iterate through the free list to find a suitable block
    void *bp;
    
    for (bp = free_list; GET_ALLOC(HDRP(bp)) == 0; bp = NEXT_FREE(bp))
    {
        
        // Check if the block is free and large enough
        if (GET_SIZE(HDRP(bp)) >= asize)
        {

            return bp; // Suitable block found
        }
    }
    return NULL; // No suitable block found
}




static void place(void* bp, size_t asize)
{


    // Retrieve the size of the entire free block
    size_t bsize = GET_SIZE(HDRP(bp));

    // Check if the remaining space after allocation is sufficient for splitting
    if ((bsize - asize) >= MINBLOCKSIZE)
    {
        // Allocate the required space and adjust the remaining free block
        // The new header and footer are set up for the remaining free space
        PUT(HDRP(bp), PACK(asize, 1));
        PUT(FTRP(bp), PACK(asize, 1));
        remove_freeblock(bp); // Remove the block from the free list
        bp = NEXT_BLKP(bp);   // Move to the next block
        PUT(HDRP(bp), PACK(bsize - asize, 0)); // Set header for the new free block
        PUT(FTRP(bp), PACK(bsize - asize, 0)); // Set footer for the new free block
        coalesce(bp); // Coalesce if adjacent blocks are free
    }
    else
    {
        // Allocate the entire block if splitting is not feasible
        PUT(HDRP(bp), PACK(bsize, 1));
        PUT(FTRP(bp), PACK(bsize, 1));
        remove_freeblock(bp); // Remove the block from the free list
    }
    
}



 
static void remove_freeblock(void *bp)
{


    if(bp) {  // Ensure bp is not NULL

    // Adjust the previous block's next pointer
    // If there is a previous free block, update its next pointer to skip the current block.
    // If there is no previous block, reset the start of the free list to the next free block.
    if (PREV_FREE(bp))
      NEXT_FREE(PREV_FREE(bp)) = NEXT_FREE(bp);
    else
      free_list = NEXT_FREE(bp);

    // Adjust the next block's previous pointer
    // If there is a next free block, update its previous pointer to skip the current block.
    if(NEXT_FREE(bp) != NULL)
      PREV_FREE(NEXT_FREE(bp)) = PREV_FREE(bp);
  }
}



c memory-management malloc
1个回答
0
投票

On your guys advice I used the profiler and it seems the malloc function itself rips the time down ? How ?

Idont quite understand the numbers in this part, I used the gprof profiler

© www.soinside.com 2019 - 2024. All rights reserved.