[英]Handle memory properly with a pool of structs
我有一個包含三個結構池的程序。 對於它們中的每一個,我使用一個使用過的結構列表,另一個用於未使用的結構。 在執行期間,程序使用結構,並根據需要將它們返回池中。 此外,還有一個垃圾收集器來清理“僵屍”結構並將它們返回到池中。
在執行開始時,虛擬內存(如預期的那樣)顯示大約10GB *的內存分配,並且當程序使用該池時,RSS內存會增加。
雖然使用的節點返回池中,標記為未使用的節點,但RSS內存不會減少。 我期待這一點,因為操作系統不知道我正在對內存做什么,無法注意到我是在真正使用它們還是管理池。
我想做的是強制未使用的內存隨時返回虛擬內存,例如,當RSS內存增加到X GB以上時。
有沒有辦法在給定內存指針的情況下標記將其放入虛擬內存的內存區域? 我知道這是操作系統的責任,但也許有辦法強迫它。
也許我不應該關心這個,你怎么看?
提前致謝。
我提供了幾個文件的池使用情況與內存使用情況的圖片。 正如您所看到的,池使用中的突然下降是由於垃圾收集器,我希望看到的是,這種下降反映在內存使用中。
只要您通過mmap而不是malloc分配內存,就可以執行此操作。 您希望將madvise函數與POSIX_MADV_DONTNEED
參數一起使用。
只需記住使用POSIX_MADV_WILLNEED
進行madvise再次使用它們之前確保它們背后有實際的內存。
這實際上並不能保證頁面會被換出,但是在有時間的情況下給內核一個強有力的暗示。
Git 2.19(Q8 2018)提供了struct的內存池示例,使用mmap
,而不是malloc
。
對於大型樹,索引需要保存在堆上分配的許多緩存條目。
現在,這些高速緩存條目從專用內存池中分配,以分攤malloc(3)
開銷。
請參閱Jameson Miller( jamill
)的 提交8616a2d , 提交8e72d67 , 提交0e58301 , 提交158dfef , 提交8fb8e3f , 提交a849735 , 提交825ed4d , 提交768d796 (2018年7月2日) 。 (由Junio C gitster
合並- gitster
-在提交ae533c4 ,2018年8月2日)
block alloc
:從mem_pool
分配緩存條目從磁盤讀取大型索引時, 部分時間在
malloc()
調用中占主導地位。
這可以通過分配大塊內存並通過內存池自行管理來緩解 。此更改將高速緩存條目分配移動到內存池之上。
設計:
index_state
結構將獲得關聯的memory_pool
的概念,cache_entries將從中分配。
當從磁盤讀取索引時,我們有關於條目數量及其大小的信息,這可以指導我們決定初始內存分配的大小。
當一個索引被丟棄時,相關的memory_pool
也將被丟棄 - 因此cache_entry
的生命周期與它所分配的index_state
的生命周期相關index_state
。對於拆分索引,遵循以下規則。
1,定義了一些術語:術語:
- '
the_index
':表示索引的邏輯視圖- '
split_index
':表示“基本”緩存條目。 從拆分索引文件中讀取。'
the_index
'可以引用單個split_index
,以及cache_entries
中的split_index
。the_index
之前,將丟棄split_index
。
這意味着當我們在存在拆分索引的情況下分配cache_entries
時,我們需要從split_index
的內存池中分配條目。這允許我們遵循
the_index
可以從the_index
引用cache_entries的split_index
,並且在仍然被引用時不會釋放cache_entries
。管理臨時cache_entry結構:
緩存條目通常是為索引分配的,但情況並非總是如此。 有時會分配緩存條目,因為這是現有
checkout_entry
函數使用的類型。
因此,現有代碼需要處理與索引/內存池關聯的緩存條目,以及僅存在於瞬時存在的緩存條目。
考慮了如何處理這個問題的幾種策略。選擇方法:
在
cache_entry
類型中添加了一個額外字段,以跟蹤cache_entry是否是從內存池中分配的。
這當前是一個int
字段,因為現有的ce_flags
位字段中沒有更多可用位。
如果/當需要更多位時,可以將該新字段轉換為適當的位字段。我們決定跟蹤和迭代已知的內存池區域比添加額外的字段來跟蹤此狀態更不可取。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.