Analysis of a generic Memory Pool

Source: Internet
Author: User
Tags netbeans

Analysis of a generic Memory Pool

By cream (LOKI)

One man's war (http://blog.csdn.net/MDL13412)

The home page of this project is.

To minimize the amount of code, I will remove some comments and replace them with my comments. In addition, for the copyright statement of the original author, I will only give it at the beginning of the article and remove it from the code later.

/*!\author Matt Wash*/

First, the project's source code folder contains eight files:

Exampleclasses. h main. cpp pool. h genericmemorypool. sln mattexampleclasses. h uncopyable. h genericmemorypool. vcproj pooledobject. h

WherePool. h pooledobject. h uncopyable. hIs the core code,Exampleclasses. h mattexampleclasses. h main. cppIs the test code,Genericmemorypool. slnAndGenericmemorypool. vcprojIt is used by Visual Studio 2003 and later organization projects. Because I analyzed it in Linux and used the IDE netbeans, these two files are of no use for my analysis, I deleted it directly, and then re-organized the project using netbeans.

Let's start from the smallestUncopyable. hStart profiling

# Ifndef uncopyable_h # define uncopyable_h // the function of the class is to prevent a class from being copied (including copying structures and assigning values) /// its principle is very simple, that is, the copy constructor and operator = are declared as private. // since they are not actually used, as long as the function declaration is not required. // then, any Class D that you do not want to copy will be inherited from uncopyable. In this way, if you perform the // copy operation on Class D, the function access permission declared by uncopyable will fail. /// For more information, see <valid tive C ++> class uncopyable {protected: uncopyable (){}~ Uncopyable () {} PRIVATE: uncopyable (const uncopyable &); uncopyable & operator = (const uncopyable &) ;}; # endif/uncopyable_h

Next we will analyzePool. h

# Ifndef pool_h # define pool_h // comment by: Cream // E-mail: mdl2009@vip.qq.com // blog: http://blog.csdn.net/mdl13412#include <New> # include "uncopyable. H "// number of instances with the highest storage capacity in the pool. An error may occur when the maximum number of instances is exceeded. // The allocation is checked in the debug version, when the maximum number is exceeded, assertconst int g_maxnumberofobjectsinpool = 1000 is triggered. // The public interface of the Code is described as follows: // static void * allocate () // allocate an instance from the pool // static void free (void * PTR) // release an instance allocated from the pool (return to pool) // static void cr Eate () // explicitly create a pool // static void destroy () // explicitly destroy the pool ////~ Pool () // destroy pool // The design of the program framework is very small and the idea is very clear. I mainly analyze the problems of memory alignment allocation. // In addition, this pool uses the singleton mode template <class T> class pool: Private uncopyable {public: static void * allocate () {// checks whether the pool has been allocated, prevent errors if (instance (). memory _ = NULL) instance (). createpool (); // check whether the pool has capacity assert (instance () in debug mode (). numfreeblocks _> 0 & "the pool is empty"); // assign the Instance Object return instance (). allocateblock ();} static void free (void * P Tr) {// check whether the pool is allocated and whether the pointer to be released is null to prevent the error if (! Instance (). Memory _ |! PTR) return; // In debug mode, check whether the other party to be released is the assert (instance () allocated in the pool (). containspointer (PTR) & "object not allocated from this pool"); // return the released memory to the pool instance (). freeblock (freeblock *) PTR);} static void create () {If (instance (). memory _ = NULL) instance (). createpool ();} static void destroy () {If (instance (). memory _! = NULL) instance (). destroypool ();}~ Pool () {destroypool ();} PRIVATE: // used to maintain the memory linked list. This struct is used to improve readability. struct freeblock {freeblock * Next;}; pool (): memory _ (null), head _ (null), blocksize _ (0) {} static pool & instance () {static pool; return pool ;} // This code is a difficult part of the framework, but it is also a highlight of void createpool () {numfreeblocks _ = g_maxnumberofobjectsinpool; // pool capacity // the size of the memory block must meet the requirements of memory alignment so that the fastest CPU addressing can be achieved. // _ alignof (t) is used to check the granularity of T alignof. Because you can specify the alignof granularity, // In the early STL memory configurator with hard code, the alignment granularity is fixed to 8. // but if the alignment is specified as 16, an error will occur. The dynamic detection here is the highlight. // For example, suppose sizeof (t) = 20, _ alignof (t) = 16 // then blocksize = 20 // diff = 20% 16 = 4 // because diff! = 0, so // blocksize + = 20 + 16-4 = 32 // This satisfies the requirements of memory alignment. A very good algorithm // There is a problem here, if sizeof (t) is smaller than a pointer, memory blocksize _ = sizeof (t); size_t diff = blocksize _ % _ alignof (t); If (diff! = 0) blocksize _ + = _ alignof (t)-diff; // Note: If the allocated blocksize is smaller than a pointer, allocate at least one pointer size if (blocksize _ <sizeof (uintptr_t) blocksize _ = sizeof (uintptr_t); Memory _ = alignedmalloc (g_maxnumberofobjectsinpool * blocksize _, _ alignof (t); // checks whether the allocated memory meets the alignof alicloud )) & "memory not aligned"); // set the freeblock linked list header to the assigned value head _ = (freeblock *) memory _; head _-> NEX T = NULL;} void destroypool () {alignedfree (memory _); Memory _ = NULL;} // checks whether a pointer is allocated in the pool, used to prevent the release of bool containspointer (void * PTR) {return (uintptr_t) PTR >=( uintptr_t) memory _ & (uintptr_t) PTR <(uintptr_t) memory _ + blocksize _ * g_maxnumberofobjectsinpool;} freeblock * allocateblock () {// The allocated block is an O (1) algorithm, the linked list header is always a freeblock * block = head _; // The number of idle nodes is maintained here, that is, the remaining pool capacity if (-- numfree Blocks _! = 0) {If (Head _-> next = NULL) {// If the block has not been previusly allocated its next pointer // will be null so just update the list head to the next block in the pool head _ = (freeblock *) (uintptr_t) Head _) + blocksize _); Head _-> next = NULL ;} else {// The block has been previusly allocated and freed so it // has a valid link to the next free Block Head _ = head _-> next;} return Block ;} Void freeblock (freeblock * block) {// return the memory to the linked list header if (numfreeblocks _> 0) block-> next = head _; head _ = block; // maintain the number of idle nodes numfreeblocks _ ++;} void * alignedmalloc (size_t size, int alignment) {// allocate enough memory. The algorithm here is classic, this algorithm was used in early STL. // first, the memory occupied by the freeblock pointer is maintained. Const int pointersize = sizeof (void *); // alignment-1 + pointersize this is the memory size required for freeblock memory alignment // the preceding example sizeof (t) = 20, _ alignof (t) = 16 ,// G_maxnumberofobjectsinpool = 1000 // then the call to this function is alignedmalloc (1000*20, 16) // then alignment-1 + pointsize = 19 const int requestedsize = size + alignment-1 + pointersize; // The actual allocated size is 20000 + 19 = 20019 void * Raw = malloc (requestedsize); // The memory address uintptr_t start = (uintptr_t) actually allocated by the real pool for the object instance) raw + pointersize; // The analysis of this algorithm can be found in the STL source code I analyzed <stl_alloc.h> 355th rows // http://blog.csdn.net/mdl13412/article/detail S/6638405 void * aligned = (void *) (start + alignment-1 )&~ (Alignment-1); // here, a memory pointing to malloc () is maintained * (void **) (uintptr_t) aligned-pointersize) = raw; // return the real address of the Instance Object return aligned ;} // memory maintained here // The Memory alignment requirements are met here // | // memory alignment/// | memory alignment padding | maintained pointer | object 1 | object 2 | object 3 | ...... | object n | // ------------------------------------------------------------------------ // ^ | point to the address starting point allocated by malloc (). // | // ----------------------- Void alignedfree (void * aligned) {// The release operation is very simple. For more information, see void * Raw = * (void **) (uintptr_t) aligned-sizeof (void *); free (raw);} bool isaligned (void * data, int alignment) {// It is a classic algorithm, see 

Summary:

Improvements:

1) The pool capacity should be customized by the user, and global variables should not be used, so the degree of freedom is very low.

2) For POOL operation macros, you can use the traits technology to distribute the compilation period based on the pod and user-defined types, instead of maintaining two sets of different macros, which can be transparent to programmers.

3) The Memory alignment check process is considered useful only when writing the framework. After the development is complete, remove it.

4) The uncopyable class can be removed, because it is not used in other places and the user will not reuse it, so you can directly declare the pool replication constructor and operator = as private.

5) This framework is not thread-safe. At least lock should be performed during pool creation; otherwise, problems may occur.

6) when the pool does not have capacity, it cannot work properly. A second-level distributor should be added to meet the efficiency requirements.

7) for objects whose sizeof is smaller than the pointer, memory will be wasted. It should be made special to provide a high-performance version.

What's better:

1) freeblock definition improves program readability

2) memory alignment allocation problems, fast speed, and can reduce the generation of memory fragments

3) The Memory alignof algorithm uses _ alignof for detection without hard code, avoiding problems caused by hard code.

4) the interface is well designed. The create () interface gives programmers the opportunity to control the pool creation.

5) the time complexity for obtaining object instances is O (1), which is good.

6) The Singleton mode is well applied.

7) the document is well written and explained :-)

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.