In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-10 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces how C++ to achieve fixed-length memory pool, has a certain reference value, interested friends can refer to, I hope you read this article after a great harvest, the following let Xiaobian take you to understand.
1. pooling technique
Pool is a design pattern often used in computer technology. Its connotation lies in: applying for the core resources that need to be used frequently in the program first, putting them into a pool, and managing them by the program itself. This can improve the efficiency of resource use and ensure the number of resources occupied by the program. Commonly used pool technologies include memory pools, thread pools, and connection pools (often used in databases), among which memory pools and thread pools are the most used.
2. Memory pool concept
Memory Pool is a dynamic memory allocation and management technique. In general, programmers are accustomed to directly using new, delete, malloc, free and other APIs to apply for allocation and release of memory, which leads to the following consequences: when the program runs for a long time, due to the variable size of the memory block applied, frequent use will cause a large number of memory fragments, thus reducing the performance of the program and the operating system. Memory pool is in the real use of memory before, first apply for allocation of a large block of memory (memory pool) reserved for spare, when the programmer applies for memory, from the pool to take out a dynamic allocation, when the programmer releases memory, the release of memory into the pool, again apply for the pool can be taken out for use, and try to merge with the surrounding free memory block. If the memory pool is insufficient, the memory pool will be automatically expanded and a larger memory pool will be requested from the operating system.
2.1 memory fragmentation
Internal debris:
An internal fragment is memory space that has been allocated (to which process it belongs) but cannot be utilized; an internal fragment is a block of memory inside a region or page. The processes occupying these regions or pages do not use this memory block. While the process owns the memory block, the system cannot utilize it. Until the process releases it, or the process ends, the system is unlikely to utilize this memory block. (The compiler will align the data. When it is not an integer multiple of the compiler's minimum alignment number, it needs to add some to ensure alignment. Then this piece added for alignment is the inner fragment)
External fragmentation (commonly referred to as memory fragmentation):
Assume that the system allocates 16 bytes, 8 bytes, 16 bytes, 4 bytes in turn, and the remaining 8 bytes are not allocated. At this time to allocate a 24byte space, the operating system recovered a top two 16 bytes, the total remaining space has 40 bytes, but can not allocate a continuous 24byte space, this is the external fragmentation problem. (There would have been enough memory, but it was impossible to request a slightly larger contiguous memory due to fragmentation)
3. Implement fixed-length memory pools
3.1 locating new expression (placement-new)
Locating a new expression is a constructor call that initializes an object in the allocated raw memory space. Use the format: new (place_address) type or new (place_address) type(initializer-list), place_address must be a pointer, initializer-list is the initialization list of types.
Usage scenario:
In practice, locating new expressions is generally used in conjunction with memory pools. Because the memory allocated by the memory pool is not initialized, if it is a custom type object, it needs to be initialized by ** using the definition expression of new.
3.2 complete implementation
That is, implement a FreeList, each FreeList used to allocate fixed-size memory blocks, such as fixed memory allocators for allocating 32-byte objects, and so on.
Advantages:
Simple and crude, high efficiency of distribution and release, effective in solving problems in specific scenarios in practice.
Disadvantages:
Single function, can only solve the fixed length of memory requirements, in addition to occupying memory without release.
Ideas realized:
First apply for a large piece of memory from memory. If necessary, cut the memory that has been applied for (reduce the number of times of dealing with the bottom of the operating system, and improve the efficiency. The memory pool must be able to solve the efficiency of applying and releasing memory)
For small blocks of memory that are not needed, instead of releasing them, use a freeList to manage them. If there is any spare space in the freeList, then the memory application will first go to the free list instead of cutting the large memory blocks that are applied for.
For this small block of memory, the first 4 or 8 bytes store the address of the next small block of memory (this is because the size of the pointer is 4 bytes on the 32-bit platform, and the pointer is 8 bytes on the 64-bit platform).
Pointer is the address, then the type of pointer is to understand the reference to get the size, for the type of memory I don't care, in the 32-bit platform I want to take out his first 4 bytes, and then store my next small memory address, so obj strong to int* type, and then dereference can get the first 4 bytes. If you are on a 64-bit platform, you should take the first 8 bytes to store the address of the next small memory, but if you write the first 4 bytes, there will be a pointer out of bounds problem. The Nextobj() interface function written in the following code is to be able to fetch the first 4 bytes or 8 bytes of small memory. The type I need is void*, which can automatically adapt to the platform (analogous to the int type above, it can be connected)
//Implement a fixed-length memory pool (named ObjectPool for a specific object)#pragma once #include"Common.h"templateclass ObjectPool{public: ~ObjectPool() { // } //There is a big problem with this code: we default to the first four bytes here, but on a 64-bit platform, we need to take the first 8 bytes of this small memory to save the address. void*& Nextobj(void* obj) { return *((void**)obj); //void* can be automatically adapted to the platform } //function interface for memory request T* New() { T* obj = nullptr; //first, you should judge freeList if (_freeList) { //Then take a piece directly from the free list obj = (T*)_freeList; //_freeList = (void*)(*(int*)_freeList); _freeList = Nextobj(_freeList); } else { //indicates that the free list is empty //Then here we have to make a judgment again, whether there is memory or not if (_leftSize
< sizeof(T)) //说明此时空间不够了 { //那么就进行切割 _leftSize = 1024 * 100; _memory = (char*)malloc(_leftSize); //对于C++来说,如果向系统申请失败了,则会抛异常 if (_memory == nullptr) { throw std::bad_alloc(); } } //进行memory的切割 obj = (T*)_memory; _memory += sizeof(T); //这里如果想不通可以画一下图,很简单 _leftSize -= sizeof(T); //表示剩余空间的大小 } new(obj)T; //定位new,因为刚申请的空间内如果是自定义类型是没有初始化的 //所以需要可以显示的调用这个类型的构造函数,这个是专门配合内存池使用的 return obj; } void Delete(T* obj) { obj->~T();//destruct custom type first //and then release, but at this time are also a piece of small memory, can not be free at one time, so you need a free list to catch these small memories //This is actually the key point of the core //For pointers, 4 bytes under 32-bit platforms and 8 bytes under 64-bit platforms //head to freeList //*((int*)obj)= (int)_freeList; Nextobj(obj) = _freeList; _freeList = obj; }private: char* _memory = nullptr;//char* is given for good size, not necessarily T* or void* int _leftSize = 0; //Why add this member variable? Because your menory += sizeof(T) might cause a problem of crossing the line. void* _freeList = nullptr; //Give some default values and let its constructor generate itself};struct TreeNode{ int _val; TreeNode* _left; TreeNode* _right; TreeNode() :_val(0) , _left(nullptr) , _right(nullptr) {}};void TestObjectPool(){ Verify that the returned memory is reused ObjectPool tnPool; TreeNode* node1 = tnPool.New(); TreeNode* node2 = tnPool.New(); cout
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.