前面有一篇文章說過在**中如果要高頻地建立乙個物件(比如一些及時通訊的socket等等)怎麼通過raii技法進行記憶體優化,而且這些物件在程式中的生存週期比較短,搞幾下就沒用了,尤其是一些執行緒之類,如果要完成什麼阻塞任務,雖然它就搞那麼幾秒,但放在主線程就是會卡住介面,讓使用者體驗很差,然而執行緒的開銷可是眾所周知的不小,這個時候我們就會想到如果有一種方法能夠反覆利用這些物件就好了,於是就有了池這個概念,最常見的就是執行緒池,這個我已經用c++在win上實現了乙個,寫的時間比較早,可能會有一些小的問題,**放在我的github上
物件池的思想其實也是很簡單的,不外乎就是乙個可以對記憶體區進行控制的資料結構,我這裡就使用乙個鍊錶簡單粗暴,先來看看**吧,我的**寫的還是比較易懂的:
struct linknode
if (capacity > max_memoryblock)
/*allocate*/
_memory = tallocator::allocate(capacity * (sizeof(u)));
if (_memory == null) throw
std::bad_alloc();
/*init*/
_capacity = capacity;
_countinnode = 0;
}//析構
~linknode()
};
看這段**只要看看我的結構體大概有什麼結構就可以了,全部的**包括在前面raii的**都放在同乙個github倉庫裡面,可以進行同時測試
這個結構體就是物件池核心結構鍊錶的乙個節點,其中有乙個指向一塊記憶體塊的指標,以及節點可容納的物件容量,以及當前節點含有的物件數,正如你所看到,我設計的物件池會將物件建立在我指定的記憶體區塊的指定偏移位置上,每乙個節點都指向一塊記憶體塊,這塊記憶體可以容納一定數量的物件,具體的數量可以由我們在初始化物件池的時候認為設定,在這個記憶體塊上,物件是連續儲存的,這種整齊的記憶體結構也有助於我的記憶體管理,當物件的數量超過當前節點的最大容量時,我就會產生新的節點,這個新節點同樣指向一塊新的記憶體區塊,不同節點指向的記憶體塊是不連續的,這樣使得記憶體的利用隔年充分(記憶體碎片),而且在程式中還設定了自增係數,即每一次產生新節點都會在原來的容量基礎上擴容,即乘上自增係數,當然每乙個節點都會有乙個最大的容量上限。
了解記憶體的安排,再來看看如何從物件池中產生乙個新的物件,為了可以實現**,我當然還設計了乙個容器來儲存所有空閒記憶體單元(乙個物件類的大小)指標,當要求產生新的物件時,先檢查在空閒鍊錶中有沒有已經**的記憶體,如果有,馬上從鍊錶中拿出來乙個就可以使用了,這個的時間複雜度明顯為o(1),還是不錯的,就算運氣不好,所有的物件都還在被外界指標引用,是在沒法給再利用了,怎麼辦呢,無所謂,大不了我們再分配一塊記憶體咯,而且這次的new是有目標的,在指定的位址進行分配,保證節點記憶體區塊的連續,這個的複雜度也為o(1),可以先看看我實現這乙個過程的**;
u* objectpool::zygoteobjfromrecycle()
/*need to allocate new memory in
the current node*/
if ((qtail->_countinnode) >= (qtail->_capacity)) newnodememory(true);
char* addr = (char*)qtail->_memory;
addr += (qtail->_countinnode)*(sizeof(u));
qtail->_countinnode++;
u* result = new(addr) u(0);
return
result;}
**很容易看懂,其實基本就是我上面闡述的意思啦,為了更加清楚地說明這個原理,我再來一張結構圖吧:
如圖紅色部分的單元為已經被使用的記憶體,綠色部分為已經**的記憶體塊,可見,它們由空閒鍊錶管理,外界的指標或者引用就可以通過空閒鍊錶再次利用了。
template
void objectpool::destroyobjpool()
}
空閒鍊錶由於在程式中作為全域性變數的成員變數,cpu會在物件池析構時收拾它,其實在全部的記憶體都釋放之後,裡面的指標已經完全失效了,家都被炸毀了,就算你認識回家的路,你還能回得去麼,在這裡再次delete會引發程式的迷失,pc都不知道跑什麼地方去,有興趣的可以那我的**嘗試一下,我的測試是沒有發現記憶體洩露問題的,而且建立幾百甚至上千個物件反覆折騰所耗費的時間也是毫秒級別的,所以說物件池模式在高頻變數建立中是可以提高效能以及節約記憶體空間,比如我的測試類有4bytes,我建立1000個,在刪除再建立1000個,很明顯物件池節約了差不多4kb的記憶體,可以完成記憶體優化,接下來會有關於linux下執行緒池的文章,本次到此結束咯。 mybatis進擊六 mybatis的物件管理體系
目錄 一 結構化資料轉換成bean 二 mybatis的物件結構 三 應用 mybatis是如何將查詢到的資料自動轉換成物件呢?1 可以使用利用map 或 json字串,橋接著轉成bean物件 2 利用反射 newinstance 然後一一賦值 mybatis不是簡單的使用反射初始化,而是進行了精心...
物件池的使用
1 乙個模板類的物件池,template class objpool objpool void bool init int nmaxcount 10 t newobj void 取得pos的物件 同時在obj中記錄在pool中的index pool unlock return pobj void d...
物件池的運用
關於物件池的應用 物件池的工作原理 物件池的工作原理的核心有兩點 使用和快取,即對於那些被頻繁使用的物件,在使用完後,不立即將它們釋放,而是將它們快取起來,以供後續的應用程式反覆使用,從而減少建立物件和釋放物件的次數,進而改善應用程式的效能。優點 能快速取出物件節省了new物件所產生的cpu,時間的...