Berkeley DB Memory Management

Source: Internet
Author: User

A typical buddy system. Code in ENV/ENV_ALLOC.C

Data:
Alloc_layout: A data structure that manages the entire block of memory (that is, a region of BDB).    Place at the beginning of this memory. Sh_tailq_head (__ADDRQ) ADDRQ; Address queue. Sort by address. Used for splitting and merging of memory blocks. All memory blocks will be placed in the address queue. #define Db_size_q_count Sizeq_head Sizeq[db_size_q_count]; Size queue. Used to quickly find available memory. 11 queue, from 1024 bytes to 1M.
                         The blocks of memory in each queue are sorted by length from large to small. The size queue places memory that is not currently in use. Alloc_element: Placed at the beginning of each memory block Sh_tailq_entry ADDRQ; Its ENTRY sh_tailq_entry Sizeq in the address queue; Its entry uintmax_t len in the size queue; The total length of this memory block is uintmax_t Ulen; User available length//only if the remaining memory (free memory block size-user required size) is greater than shalloc_fragment, do memory splitting # define shalloc_fragment (sizeof (alloc_element) + 64)//to the specified memory size len, Q returns the corresponding size queue. Head points to the current region of the alloc_layout. #define Set_queue_for_size (head, Q, I, Len) do {for (i = 0; i < db_size _q_count; ++i) {q = & (head)->sizeq[i]; if (len) <= (u_int64_t) 1024x768 << i) break; }} while (0)//a alloc_element occupies a memory size. Need to align # define db_alloc_size (len) (size_t) db_align ((len) + sizeof (alloc_element), sizeof (UINTMA x_t))
Initialize, __env_alloc_init ():

Reginfo->head for Alloc_layout. Initializes its address queue, size queue.
The rest of the memory is initialized to a alloc_element, placed in the address queue andsizeq[DB_SIZE_Q_COUNT - 1]
Note: It is possible that the region initialization size is less than 1M, put into sizeq[DB_SIZE_Q_COUNT - 1] no relationship, the first allocation of memory will put it into the appropriate size queue.

allocating memory, __env_alloc ():

Heap-based memory allocation (malloc), which is not discussed here.

Head = infop->head;//The Alloc_layout object for this regionTotal_len = Db_alloc_size (len);//The amount of memory that needs to be allocatedSet_queue_for_size (head, Q, I, Total_len);//find the corresponding size queue     for(elp = NULL;; ++q) {//if the current size queue is not found, go to the larger size queue forSh_tailq_foreach (elp_tmp, Q, Sizeq, __alloc_element) {//traverse the current size queue            if(Elp_tmp->len < Total_len)//The size of the elements in the queue is sorted from large to small. If the current element is not large enough, then the following must not be enough                 Break; ELP= Elp_tmp;//this memory block satisfies the condition. Caches this alloc_element. If more appropriate, the ELP will be re-assigned.            if(Elp_tmp->len-total_len <= shalloc_fragment)//Use the current block of memory without splitting. Make sure to find the right size free memory (no more small, or no need to split)                 Break; }        if(elp! = NULL | | ++i >= db_size_q_count)//found in the current queue, or all size queue is not found.             Break; }    if(ELP = =NULL) {//Check out all size queue not found suitable memory case ...//if possible, extend the current region memory block, retry. otherwise exits.    }
Below is the case where the appropriate memory has been found Sh_tailq_remove (q, ELP, Sizeq, __alloc_element); //remove it from the corresponding size queue. if(Elp->len-total_len > Shalloc_fragment) {//need to do a memory splitFrag = (Alloc_element *) ((u_int8_t *) ELP + Total_len);//new block of memory after splittingFrag->len = Elp->len-Total_len; Frag->ulen =0; ELP->len =Total_len;//The original memory block is reduced by Sh_tailq_insert_after (//the segmented new memory block is placed exactly after the address queue of the original memory block.&head->Addrq, ELP, Frag, ADDRQ, __alloc_element); __env_size_insert (head, Frag); //new memory block into size queue} P= (u_int8_t *) ELP +sizeof(alloc_element); ELP->ulen = Len;//Elp is a block of memory returned to the user
Free memory, __env_alloc_free ():
Head = infop->head;//The Alloc_layout object for this regionp =ptr; ELP= (Alloc_element *) (P-sizeof(alloc_element));//get the Alloc_element object that needs to free up memoryElp->ulen =0;//Ulen is 0, indicating that this memory is no longer used//The elements in the address queue are sorted by their addresses.    if((elp_tmp =Sh_tailq_prev (&AMP;HEAD-&GT;ADDRQ, ELP, ADDRQ, __alloc_element))! = NULL &&//elp_tmp Element set to this ELP before the address queueElp_tmp->ulen = =0&&//the previous element was not used(u_int8_t *) elp_tmp + Elp_tmp->len = = (u_int8_t *) elp) {//and the two-segment address is adjacentSh_tailq_remove (&AMP;HEAD-&GT;ADDRQ, ELP, ADDRQ, __alloc_element);//merges the current memory with the previous memory. Current memory block removal ADDRQSet_queue_for_size (head, Q, I, elp_tmp->Len); Get the size of the previous element, queue Sh_tailq_remove (q, Elp_tmp, Sizeq, __alloc_element); //The previous block of memory removes its corresponding size queueElp_tmp->len + = elp->len;//do mergeELP = elp_tmp;//the ELP points to the merged memory address    }    if((elp_tmp = Sh_tailq_next (ELP, ADDRQ, __alloc_element))! = NULL &&//elp_tmp Element set for this elp after the adress queueElp_tmp->ulen = =0&&//the subsequent element is not used(u_int8_t *) elp + Elp->len = = (u_int8_t *) elp_tmp) {//and the two-segment address is adjacentSh_tailq_remove (&AMP;HEAD-&GT;ADDRQ, Elp_tmp, ADDRQ, __alloc_element);//merges the current memory with the memory behind it. Remove ADDRQ after memory blockSet_queue_for_size (head, Q, I, elp_tmp->Len); Gets the size of the element after the queue sh_tailq_remove (q, Elp_tmp, Sizeq, __alloc_element); //back block of memory remove size queueElp->len + = elp_tmp->len;//do merge. ELP points to merged memory address} __env_size_insert (head, ELP); //merged memory block into size queue

__env_size_insert (): Inserts a alloc_element into its corresponding size queue.

Set_queue_for_size (head, Q, I, Elp->len);//find its corresponding size queueSh_tailq_foreach (elp_tmp, Q, Sizeq, __alloc_element)//Traverse this size queue        if(Elp->len >= Elp_tmp->len)//Size the queue element is sorted from large to small, and the elp size is between the current element and the previous element (the previous element may be empty). Need to be inserted before the current elp_tmp             Break; if(Elp_tmp = =NULL) Sh_tailq_insert_tail (q, ELP, Sizeq); //elp into the tail of the team    ElseSh_tailq_insert_before (q, Elp_tmp, ELP, Sizeq, __alloc_element);//the ELP is inserted before the current elp_tmp

Note : Env_alloc/env_alloc_free is not locked. The call to it requires a lock of the corresponding region.

Berkeley DB Memory Management

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.