星期二, 10月 14, 2014

如何決定何時從 Partition 何時從 Heap allocate memory


在嵌入式系統當中, 對memory 的使用有一些很有用的技巧,
有一本書寫得非常好, 推薦給大家
書名是 <> By Charles Weir and James Noble

英文版的網頁在這裡 (有on line 版本可以看哦)

中文版是侯捷翻譯的 (現在還有人認識他嗎 ?)


其中有一個技巧, 叫做 Partition Memory,
所謂的 Partition Memory 就是預先規劃好一堆固定大小的 memory 來給程式使用,
每次取用和歸還的單位是以一個 Partition為主.
舉一個常見的的設定如下
/* 定義在 const.h */

/* 定義了四種 Partition 的大小 */
#define PARTITION_A_SIZE                  60
#define PARTITION_B_SIZE                 250
#define PARTITION_C_SIZE                 600
#define PARTITION_D_SIZE               1600

/* 定義每一種 Partition 的個數 */
#define POOL_A_PARTITIONS             100
#define POOL_B_PARTITIONS             100
#define POOL_C_PARTITIONS              50
#define POOL_D_PARTITIONS              15

上面這樣的設定表示 Partition A 這個 group 的 memory block有100 個,
每一個 block的大小是 60 bytes. 以此類推.
所以就算程式只要 allocate 1 個 byte,
系統至少也會給一塊 partition, 也就是60 bytes. (標準的要五毛給一塊)

這樣的好處是 allocate 的速度比較快,(就是演算法比較簡單)
也不容易發生 fragmentation 的問題. (這個問題不懂, 請回去問學校老師)

通常使用 malloc() 這樣的 memory allocate interface 來 allocate 記憶體時,
只要需要的 size 沒有超過最大的 Partition size (以上面這個例子來說, 就是1600 bytes)
就會從 Partition Pool 裡面 allocate memory.

如果超過最大的 Partition size 就會從 Heap 裡面 allocate memory.

Partition memory 在使用上有一個通常的行為
就是小塊的 partition 如果都被用完了
會自動找次大塊的 partition.
所以 Partition A 用光了, 會去 Partition B 的Pool 中要 memory.

但是最大的那一塊 partition 被要光了之後,
並不會去heap 裡面要,
反而會回報 Software Exception – No More Partition. (懂了嗎 ! 這是故意的)

這是因為系統管理者會根據整個系統的需求,
在開發過程中, 持續調整 partition 的個數和大小,
不會無限制地加大 Partition.

最理想的狀況是可以把所有的 Partition 放在 Internal RAM, (跟CPU封裝在一起的RAM)
這可以加快 memory 存取速度.


一旦 Partition  會被使用光,
可能是系統的問題,
也可能是軟體設計和實做的問題, 需要盡快處理.

有兩個常發生的問題,
大家可以參考我們的解決方法


第一個是大量 allocate 很小的記憶體,
例如一下子 allocate 300個 20 bytes 的 memory,

第二個是剛好 allocate 的 memory 落在最大的 partition 當中 (個數很少記得嗎 ?)
而且需求的個數剛好超過最大的 partition 的個數,
例如 allocate 20 個1000 bytes 的memory.

如果某些軟體模組在使用 memory 時,
allocate 的大小和個數都不固定 (通常是該死的3rd party library).
建議使 malloc_heap()  這類的 interface,
強制直接跟 Heap 來 allocate memory,
以免 Partition Pool 被使用光所產生的 memory 問題,

沒有留言: