日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

提高C++性能的编程技术笔记:多线程内存池+测试代码

發(fā)布時間:2023/11/27 生活经验 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 提高C++性能的编程技术笔记:多线程内存池+测试代码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為了使多個線程并發(fā)地分配和釋放內存,必須在分配器方法中添加互斥鎖。

全局內存管理器(通過new()和delete()實現)是通用的,因此它的開銷也非常大。

因為單線程內存管理器要比多線程內存管理器快的多,所以如果要分配的大多數內存塊限于單線程中使用,那么可以顯著提升性能。

如果開發(fā)了一套有效的單線程分配器,那么通過模板可以方便地將它們擴展到多線程環(huán)境中。

以下是測試代碼(multi_threaded_memory_pool.cpp):

#include "multi_threaded_memory_pool.hpp"
#include <iostream>
#include <chrono>
#include <string>
#include <mutex>namespace multi_threaded_memory_pool_ {// reference: 《提高C++性能的編程技術》:第七章:多線程內存池class Rational1 {
public:Rational1(int a = 0, int b = 1) : n(a), d(b) {}
private:int n; // 分子int d; // 分母
};// 單線程可變大小內存管理器: 
// MemoryChunk類取代之前版本中使用的NextOnFreeList類,它用來把不同大小的內存塊連接起來形成塊序列
class MemoryChunk {
public:MemoryChunk(MemoryChunk* nextChunk, size_t chunkSize);// 析構函數釋放構造函數獲得的內存空間~MemoryChunk() { delete [] mem; }inline void* alloc(size_t size);inline void free(void* someElement);// 指向列表下一內存塊的指針MemoryChunk* nextMemChunk() { return next; }// 當前內存塊剩余空間大小size_t spaceAvailable() { return chunkSize - bytesAlreadyAllocated; }// 這是一個內存塊的默認大小enum { DEFAULT_CHUNK_SIZE = 4096 };private:MemoryChunk* next;void* mem;// 一個內存塊的默認大小size_t chunkSize;// 當前內存塊中已分配的字節(jié)數size_t bytesAlreadyAllocated;
};// 構造函數首先確定內存塊的適當大小,然后根據這個大小從堆上分配私有存儲空間
// MemoryChunk將next成員指向輸入參數nextChunk, nextChunk是列表先前的頭部
MemoryChunk::MemoryChunk(MemoryChunk* nextChunk, size_t reqSize)
{chunkSize = (reqSize > DEFAULT_CHUNK_SIZE) ? reqSize : DEFAULT_CHUNK_SIZE;next = nextChunk;bytesAlreadyAllocated = 0;mem = new char[chunkSize];
}// alloc函數處理內存分配請求,它返回一個指針,該指針指向mem所指向的MemoryChunk私有存儲空間中的可用空間。
// 該函數通過更新該塊中已分配的字節(jié)數來記錄可用空間的大小
void* MemoryChunk::alloc(size_t requestSize)
{void* addr = static_cast<void*>(static_cast<char*>(mem) + bytesAlreadyAllocated);bytesAlreadyAllocated += requestSize;return addr;
}// 在該實現中,不用擔心空閑內存段的釋放。當對象被刪除后,整個內存塊將被釋放并且返回到堆上
inline void MemoryChunk::free(void* doomed)
{
}// MemoryChunk只是一個輔助類,ByteMemoryPoll類用它來實現可變大小的內存管理
class ByteMemoryPool {
public:ByteMemoryPool(size_t initSize = MemoryChunk::DEFAULT_CHUNK_SIZE);~ByteMemoryPool();// 從私有內存池分配內存inline  void* alloc(size_t size);// 釋放先前從內存池中分配的內存inline void free(void* someElement);private:// 內存塊列表,它是我們的私有存儲空間MemoryChunk* listOfMemoryChunks = nullptr;// 向我們的私有存儲空間添加一個內存塊void expandStorage(size_t reqSize);
};// 雖然內存塊列表可能包含多個塊,但只有第一塊擁有可用于分配的內存。其它塊表示已分配的內存。
// 列表的首個元素是唯一能夠分配可以內存的塊。// 構造函數接收initSize參數來設定一個內存塊的大小,即構造函數借此來設置單個內存塊的大小。
// expandStorage方法使listOfMemoryChunks指向一個已分配的MemoryChunk對象
// 創(chuàng)建ByteMemoryPool對象,生成私有存儲空間
ByteMemoryPool::ByteMemoryPool(size_t initSize)
{expandStorage(initSize);
}// 析構函數遍歷內存塊列表并且刪除它們
ByteMemoryPool::~ByteMemoryPool()
{MemoryChunk* memChunk = listOfMemoryChunks;while (memChunk) {listOfMemoryChunks = memChunk->nextMemChunk();delete memChunk;memChunk = listOfMemoryChunks;}
}// alloc函數確保有足夠的可用空間,而把分配任務托付給列表頭的MemoryChunk
void* ByteMemoryPool::alloc(size_t requestSize)
{size_t space = listOfMemoryChunks->spaceAvailable();if (space < requestSize) {expandStorage(requestSize);}return listOfMemoryChunks->alloc(requestSize);
}// 釋放之前分配的內存的任務被委派給列表頭部的MemoryChunk來完成
// MemoryChunk::free不做任何事情,因為ByteMemoryPool的實現不會重用之前分配的內存。如果需要更多內存,
// 我們將創(chuàng)建新的內存塊以便今后分配使用。在內存池被銷毀時,內存釋放回堆中。ByteMemoryPool析構函數
// 釋放所有的內存塊到堆中
inline void ByteMemoryPool::free(void* doomed)
{listOfMemoryChunks->free(doomed);
}// 若遇到內存塊用盡這種不太可能的情況,我們通過創(chuàng)建新的內存塊并把它添加到內存塊列表的頭部來擴展它
void ByteMemoryPool::expandStorage(size_t reqSize)
{listOfMemoryChunks = new MemoryChunk(listOfMemoryChunks, reqSize);
}// 多線程內存池實現
template<class POOLTYPE, class LOCK>
class MTMemoryPool {
public:// 從freeList里分配一個元素inline void* alloc(size_t size);// 返回一個元素給freeListinline void free(void* someElement);private:POOLTYPE stPool; // 單線程池LOCK theLock;
};// alloc方法將分配任務委托給內存池成員,而將鎖定任務委托給鎖成員
template<class M, class L>
inline void* MTMemoryPool<M, L>::alloc(size_t size)
{void* mem;theLock.lock();mem = stPool.alloc(size);theLock.unlock();return mem;
}template<class M, class L>
inline void MTMemoryPool<M, L>::free(void* doomed)
{theLock.lock();stPool.free(doomed);theLock.unlock();
}class ABCLock { // 抽象基類
public:virtual ~ABCLock() {}virtual void lock() = 0;virtual void unlock() = 0;
};class MutexLock : public ABCLock {
public:MutexLock() {}~MutexLock() {}inline void lock() { mtx.lock(); }inline void unlock() { mtx.unlock(); }private:std::mutex mtx; 
};class Rational2 {
public:Rational2(int a = 0, int b = 1) : n(a),d(b) {}void* operator new(size_t size) { return memPool->alloc(size); }void operator delete(void* doomed, size_t size) { memPool->free(doomed); }static void newMemPool() { memPool = new MTMemoryPool<ByteMemoryPool, MutexLock>; }static void deleteMemPool() { delete memPool; }private:int n; // 分子int d; // 分母static MTMemoryPool<ByteMemoryPool, MutexLock>* memPool;
};MTMemoryPool<ByteMemoryPool, MutexLock>* Rational2::memPool = nullptr;///
// 多線程內存池實現應用在單線程環(huán)境中
class DummyLock : public ABCLock {
public:inline void lock() {}inline void unlock() {}
};class Rational3 {
public:Rational3(int a = 0, int b = 1) : n(a),d(b) {}void* operator new(size_t size) { return memPool->alloc(size); }void operator delete(void* doomed, size_t size) { memPool->free(doomed); }static void newMemPool() { memPool = new MTMemoryPool<ByteMemoryPool, DummyLock>; }static void deleteMemPool() { delete memPool; }private:int n; // 分子int d; // 分母static MTMemoryPool<ByteMemoryPool, DummyLock>* memPool;
};MTMemoryPool<ByteMemoryPool, DummyLock>* Rational3::memPool = nullptr;int test_multi_threaded_memory_pool_1()
{using namespace std::chrono;high_resolution_clock::time_point time_start, time_end;const int cycle_number1{10000}, cycle_number2{1000};{ // 測試全局函數new()和delete()的基準性能Rational1* array[cycle_number2];time_start = high_resolution_clock::now();for (int j =0; j < cycle_number1; ++j) {for (int i =0; i < cycle_number2; ++i) {array[i] = new Rational1(i);}for (int i = 0; i < cycle_number2; ++i) {delete array[i];}	}time_end = high_resolution_clock::now();fprintf(stdout, "global function new/delete time spent: %f seconds\n",(duration_cast<duration<double>>(time_end - time_start)).count());
}{ // 多線程內存池測試代碼Rational2* array[cycle_number2];time_start = high_resolution_clock::now();Rational2::newMemPool();for (int j = 0; j < cycle_number1; ++j) {for (int i = 0; i < cycle_number2; ++i) {array[i] = new Rational2(i);}for (int i = 0; i < cycle_number2; ++i) {delete array[i];}}Rational2::deleteMemPool();time_end = high_resolution_clock::now();fprintf(stdout, "multi-threaded variable-size memory manager time spent: %f seconds\n",(duration_cast<duration<double>>(time_end - time_start)).count());	
}{ // 多線程內存池應用在單線程環(huán)境下測試代碼Rational3* array[cycle_number2];time_start = high_resolution_clock::now();Rational3::newMemPool();for (int j = 0; j < cycle_number1; ++j) {for (int i = 0; i < cycle_number2; ++i) {array[i] = new Rational3(i);}for (int i = 0; i < cycle_number2; ++i) {delete array[i];}}Rational3::deleteMemPool();time_end = high_resolution_clock::now();fprintf(stdout, "multi-threaded variable-size memory manager in single-threaded environment time spent: %f seconds\n",(duration_cast<duration<double>>(time_end - time_start)).count());	
}return 0;
}} // namespace multi_threaded_memory_pool_

執(zhí)行結果如下:

GitHub:https://github.com/fengbingchun/Messy_Test ?

總結

以上是生活随笔為你收集整理的提高C++性能的编程技术笔记:多线程内存池+测试代码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。