Partner Algorithm of Memory Allocation Algorithm

Source: Internet
Author: User
References:
  1. Http://blog.csdn.net/zhouzhanglong/archive/2009/04/17/4086349.aspx
Next fit Algorithm

First, we used a malloc version from the C programming language for comparison.

The idea of this simple version is to use a cyclic single-chain table to maintain idle blocks. The base variable indicates the head of the linked list, And freep indicates the idle blocks of the last operation (malloc or free.

When allocating blocks of a certain size, start with freep and find that the size of an idle block is greater than or equal to the size of the request block. If the size is good, it will be allocated directly. Otherwise, the request size blocks will be allocated from the end, and the remaining size will be changed to the new idle block, the advantage of this is that you do not need to maintain a pointer pointing to the idle block before freep, but only need to change the size value. This algorithm is called next fit in the operating system terminology.

This algorithm is random, so block allocation is generally average.

 

The content of malloc. H is as follows:

# Ifndef _ malloc_h _ <br/> # DEFINE _ malloc_h _ <br/> typedef long align; <br/> Union header {<br/> struct {<br/> Union header * PTR; <br/> unsigned size; <br/>} s; <br/> align X;/* used for alignment */<br/>}; <br/> typedef Union header; <br/> void * malloc (unsigned ); <br/> void free (void *); <br/> # endif

 

The following are the definitions of malloc and free functions:

# Include "malloc. H "<br/> # include <stddef. h> <br/> static header base;/* The Beginning of the free block list */<br/> static header * freep = NULL; /* pointer to the block we just dealing with */<br/> static header * morecore (unsigned Nu); <br/> void * malloc (unsigned nbytes) <br/> {<br/> header * P, * prevp; <br/> unsigned nunits; <br/> nunits = (nbytes + sizeof (header)-1) /sizeof (header) + 1; <br/> If (prevp = freep) = NULL) <br/>{< br/> base. s. PTR = freep = prevp = & base; <br/> base. s. size = 0; <br/>}< br/> for (P = prevp-> S. PTR; prevp = P, P = p-> S. PTR) <br/>{< br/> If (p-> S. size >=nunits) <br/>{< br/> If (p-> S. size = nunits) <br/> prevp-> S. PTR = p-> S. PTR; <br/> else <br/> {<br/> P-> S. size-= nunits; <br/> P + = p-> S. size; <br/> P-> S. size = nunits; <br/>}< br/> freep = prevp; <br /> Return (void *) (p + 1); <br/>}< br/> If (P = freep) <br/> If (P = morecore (nunits) = NULL) <br/> return NULL; <br/>}< br/> return 0; <br/>}< br/> void free (void * AP) <br/>{< br/> header * bp, * P; <br/> BP = (header *) AP-1; <br/> for (P = freep ;! (BP> P & BP <p-> S. PTR); P = p-> S. PTR) <br/> If (P> = p-> S. PTR & (BP> p | bp <p-> S. PTR) <br/> break; <br/> If (BP + bp-> S. size = p-> S. PTR) <br/>{< br/> BP-> S. size + = p-> S. PTR-> S. size; <br/> BP-> S. PTR = p-> S. PTR-> S. PTR; <br/>}< br/> else <br/>{< br/> BP-> S. PTR = p-> S. PTR; <br/>}< br/> If (p + P-> S. size = bp) <br/>{< br/> P-> S. size + = BP-> S. size; <br/> P-> S. PTR = BP-> S. PTR; <br/>}< br/> else <br/> P-> S. PTR = bp; <br/> freep = P; <br/>}< br/> # define nalloc 1024 <br/> static header * morecore (unsigned Nu) <br/>{< br/> char * CP, * sbrk (INT); <br/> header * up; <br/> If (Nu <nalloc) <br/> Nu = nalloc; <br/> CP = sbrk (Nu * sizeof (header); <br/> If (Cp = (char *)-1) <br/> return NULL; <br/> up = (header *) CP; <br/> up-> S. size = Nu; <br/> free (void *) (uP + 1); <br/> return freep; <br/>}

Buddy algorithm (partner algorithm)

As described in the reference algorithm, the core idea of the partner algorithm is to set the block size, usually the power of 2.

Here we have a maximum power value, called u, that is, the maximum block is as large as 2 ^ U.

There is a minimum power value called L. The minimum block size is as large as 2 ^ L.

Blocks of different sizes are managed using different linked lists. A free_area array is used to store the headers of these linked lists. The subscript in the array free_area indicates the power of the block size corresponding to the linked list.

Then, when allocating idle blocks, you can start searching for the smallest blocks that are larger than the applied size. If the power of the applied block is 7, search from free_area [7. If the linked list is empty, search for the large linked list. If it is found, split the large List into two small blocks, one of which is used for allocation, the other one is used to store small blocks in the linked list.

 

Here, I use a two-way linked list.

In the free process, check whether the adjacent blocks of the released block are idle. The adjacent blocks are called Buddy ). If the partner is also idle blocks, merge the two blocks. This process is recursive and cannot be merged.

The following is the definition of the function in buddy. h:

# Ifndef _ buddy_h _ <br/> # DEFINE _ buddy_h _ <br/> void * buddy_alloc (unsigned INT); <br/> void buddy_free (void *); <br/> void buddy_showblocks (); <br/> # endif

The following data structures and function definitions:

# Include "buddy. H "<br/> # include <stdio. h> <br/> # include <stddef. h> <br/>/* u = 15, L = 6 */<br/> # define buf_size 32768 <br/> # define min_order 6 <br/> # define max_order 15 <br/> typedef long align; <br/> Union header {<br/> struct {<br/> Union header * Next; <br/> Union header * Prev; <br/> unsigned size; <br/>} s; <br/> align X;/* used for alignment */<br/>}; <br/> typedef Union header; <br /> Static char buffer [buf_size]; <br/> static header * free_area [max_order + 1] = {null}; <br/> static header * free_buf = NULL; <br/> unsigned int round2power (unsigned int num) <br/>{< br/> unsigned int init = 1 <min_order; <br/> unsigned int COUNT = min_order; <br/> while (init <num) <br/>{< br/> init <= 1; <br/> count ++; <br/>}< br/> return count <= max_order? Count: max_order; <br/>}< br/> static void insert (header ** listp, header * block) <br/> {<br/> header * Prev = NULL, * Current = * listp; </P> <p> If (* listp = NULL) <br/>{< br/> * listp = block; <br/> block-> S. prev = NULL; <br/> block-> S. next = NULL; <br/> return; <br/>}< br/> while (current! = NULL) <br/>{< br/> If (prev = NULL & Block <Current) <br/>{< br/> * listp = block; <br/> block-> S. next = current; <br/> current-> S. prev = block; <br/> block-> S. prev = NULL; <br/> return; <br/>}< br/> If (Block <Current) <br/>{< br/> Prev-> S. next = block; <br/> block-> S. prev = Prev; <br/> block-> S. next = current; <br/> current-> S. prev = block; <br/> return; <br/>}</P> <p> Prev = current; <br/> C Urrent = Current-> S. Next; <br/>}< br/> If (prev! = NULL) <br/>{< br/> Prev-> S. next = block; <br/> block-> S. prev = Prev; <br/> block-> S. next = NULL; <br/> return; <br/>}< br/> static void Delete (header ** listp, header * block) <br/>{< br/> If (* listp = NULL) <br/> return; <br/>/* If the block is the head of the list */<br/> If (* listp = block) <br/>{< br/> * listp = block-> S. next; <br/>}< br/> If (Block-> S. prev! = NULL) <br/>{< br/> block-> S. prev-> S. next = block-> S. next; <br/>}< br/> If (Block-> S. next! = NULL) <br/>{< br/> block-> S. next-> S. prev = block-> S. prev; <br/>}< br/> return; <br/>}< br/> static int continous (header * P1, header * P2) <br/>{< br/> char * ptr1 = (char *) P1; <br/> char * ptr2 = (char *) P2; <br/> return (ptr1 + p1-> S. size) = ptr2; <br/>}< br/> static header * combine (header * P1, header * P2) <br/>{< br/> If (P1-> S. size! = P2-> S. size) <br/> return NULL; <br/> P1-> S. size <= 1; <br/> return P1; <br/>}< br/> void * buddy_alloc (unsigned int nbytes) <br/>{< br/> header * P; <br/> unsigned nunits, idx; <br/> int I; <br/> idx = round2power (nbytes + sizeof (header); <br/>/* initilize the header block */<br/> If (free_buf = NULL) <br/> {<br/> free_buf = free_area [max_order] = (header *) buffer; <br/> free_area [max_order]-> S. next = NULL; <br/> free_area [max_order]-> S. prev = NULL; <br/> free_area [max_order]-> S. size = 1 <max_order; <br/>}< br/> for (I = idx; I <= max_order; I ++) <br/>{< br/> If (free_area [I]! = NULL) <br/>{< br/> unsigned Int J = I-1; <br/> unsigned int size = 1 <J; <br/> header * firstp, * secondp; <br/> for (firstp = free_area [I]; j> = idx; j --, size> = 1) <br/>{< br/> secondp = (header *) (char *) firstp + size); <br/> secondp-> S. next = NULL; <br/> secondp-> S. prev = NULL; <br/> secondp-> S. size = size; <br/> insert (& free_area [J], secondp); <br/>}< br/> free_area [I] = firstp-> S. nex T; <br/> P = firstp; <br/> P-> S. next = NULL; <br/> P-> S. prev = NULL; <br/> P-> S. size = 1 <idx; <br/> return p + 1; <br/>}< br/> return NULL; <br/>}< br/> void buddy_free (void * bp) <br/> {<br/> header * Prev, * P, * next; <br/> unsigned int idx; <br/> P = (header *) BP-1; <br/> idx = round2power (p-> S. size); <br/> insert (& free_area [idx], p); <br/> Prev = p-> S. prev; <br/> next = p-> S. next; <br />/* Check whether the Buddies can be combined into the larger one */<br/> If (prev! = NULL) <br/>{< br/> If (Continous (prev, p) <br/>{< br/> Delete (& free_area [idx], p); <br/> Delete (& free_area [idx], Prev); <br/> Prev = combine (prev, P ); <br/> buddy_free (void *) (prev + 1); <br/> return; <br/>}< br/> If (next! = NULL) <br/>{< br/> If (Continous (p, next) <br/>{< br/> Delete (& free_area [idx], p); <br/> Delete (& free_area [idx], next); <br/> next = combine (p, next ); <br/> buddy_free (void *) (Next + 1); <br/> return; <br/>}< br/> void buddy_showblocks_test (); <br/> void buddy_showblocks () <br/>{< br/> buddy_showblocks_test (); <br/> unsigned int size = 1 <min_order; <br/> int I; <br/> unsigned Int bsize; <br/> header * bp; <br/> char * PTR = buffer; <br/> char * buf_end = & buffer [buf_size-1] + 1; <br/> for (BP = (header *) PTR; PTR <buf_end; PTR + = size, BP = (header *) PTR) <br/>{< br/> bsize = BP-> S. size; <br/> unsigned int tmpsize = bsize/size; <br/> int idx = round2power (bsize); <br/> header * TP = free_area [idx]; </P> <p> while (TP! = NULL) <br/> If (TP = bp) <br/> break; <br/> else <br/> TP = TP-> S. next; <br/> If (TP! = NULL) <br/>{< br/> for (I = 0; I <tmpsize; I ++) <br/>{< br/> printf ("---/N "); <br/>}< br/> else <br/> {<br/> for (I = 0; I <tmpsize; I ++) <br/>{< br/> printf ("***/N "); <br/>}</P> <p >}< br/> void buddy_showblocks_test () <br/>{< br/> int I; </P> <p> for (I = min_order; I <= max_order; I ++) <br/>{< br/> If (free_area [I]! = NULL) <br/>{< br/> header * TMP = free_area [I]; <br/> Int J; <br/> for (j = 0; TMP! = NULL; j ++, TMP = TMP-> S. next) <br/>; <br/> printf ("% d has blocks: % d/N", I, j ); <br/>}< br/> else <br/> printf ("% d is empty. /n ", I); <br/>}< br/>}

 

We can see that the partner algorithm is better at processing scattered blocks. Compared with the next fit algorithm, the partner algorithm reduces external fragmentation (external fragments, that is, holes between allocated blocks), but increases internal fragmentation (internal fragments, that is, some of them are not used in the Application Block ).

 

After testing, 100 random Size Blocks ranging from 20 to 120 were allocated and then randomly released from these blocks.

The result is that the number of fragments of next fit is 16, and the number of Buddy is 11.

From this number, we can see that buddy is indeed better than next fit for fragment processing.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.