1

是否可以將內存映射文件包裝起來?使用內存映射文件實現虛擬內存

TVirtualMemoryManager = class 
public 
    function AllocMem (Size : Integer) : Pointer; 
    procedure FreeMem (Ptr : Pointer); 
end; 

由於內存映射文件API函數全部取偏移量,我不知道如何管理內存映射文件中的空閒區域。我唯一的想法是實現某種基本的內存管理(維護不同塊大小的免費列表),但我不知道這將是多麼有效。

編輯:我真的想(大衛清楚地向我)是這樣的:

IVirtualMemory = interface 
    function ReadMem (Addr : Int64) : TBytes; 
    function AllocateMem (Data : TBytes) : Int64; 
    procedure FreeMem (Addr : Int64); 
end; 

我需要的字節連續塊(每個比較小)存儲在虛擬內存中,並能夠使用64位地址將它們讀回到內存中。大部分時間訪問是隻讀的。如果需要寫入,我將僅使用FreeMem,然後再使用AllocMem,因爲無論如何,大小都會有所不同。

我要爲內存的封裝映射文件與該接口。它在內部具有內存映射文件的句柄,並在每個ReadMem請求上使用MapViewOfFile。 64位整數只是內存映射文件的偏移量。一個懸而未決的問題是如何分配這些地址 - 我目前保留了我維護的空閒塊列表。

+1

「虛擬內存」是什麼意思?系統已經爲你做了。 –

+0

我想繞過2/3/4 GB的內存限制,並希望由文件(本例中爲頁面文件)支持的虛擬內存。 – jpfollenius

+0

在這種情況下,您需要與此不同的界面。你需要一個能夠讓你通過地址空間限制的接口,但這不是。 –

回答

2
  1. 你的建議,即「內部,它有一個句柄內存映射文件,並在每個ReadMem要求使用MapViewOfFile」將只是一個CPU資源的浪費,恕我直言。

  2. 值得一說的是你的GetMem/FreeMem要求將無法突破3/4 GB屏障。由於所有分配的內存都會映射到內存中,直到調用FreeMem,所以與普通的Delphi內存管理器一樣,內存空間不足。你能做的最好的就是依靠FastMM4,並改變你的程序來減少它的內存使用。

  3. 恕我直言,你必須改變/更新你的規範。例如,您的「更新」問題聽起來就像是一個常規的存儲問題。

你想要的是能夠分配超過3/4 GB數據的應用程序。您在我們的SynBigTable開放源代碼單元中具有這種功能的工作實現。這是純德爾福公司的一個快速和輕量級的解決方案NoSQL

它能夠創建任何大小的文件(僅64位有限),然後將每個記錄的內容映射到存儲器中,在請求。如果可能,它將使用文件的內存映射。您可以使用TSynBigTable方法直接實現您的界面:ReadMem=Get, AllocMem=Add, FreeMem=Delete。這些ID將是您的pointer類似的值,將使用RawByteString而不是TBytes

可以訪問使用整數ID,或一個字符串ID數據的任何塊,或甚至使用一個複雜的場佈局(該記錄內,或如在內存中的元數據 - 包括索引和快速搜索)。

還是依靠常規的嵌入式SQL數據庫上。例如,SQLite3非常擅長處理BLOB字段,並且能夠存儲大量的數據。通過簡單的內存緩存機制來處理大多數使用過的記錄,它可能是一個強大的解決方案。

+0

這個想法大概是當內存不再需要時取消映射。 –

+0

@DavidHeffernan這就是爲什麼即使在問題中的新的ReadMem方法接口是不夠的。使用存儲庫將依賴於請求分配內存。正如我的第一點所言,映射和取消映射會產生成本 - 這些API並非專爲小塊內存而設計的,例如[最小x86分頁爲4 KB](http://en.wikipedia.org/wiki/Page_ (computer_memory)),每個內存映射都需要額外的內存(Windows句柄,額外的內存結構......)。 –

+0

@DavidHeffernan這個問題的問題是,技術設計已經修復 - 恕我直言,是錯誤的。存儲器映射不可用於OP提議的內容。這不會有效。因此,我建議進入另一個方向來解決原始的軟件需求:處理大量的存儲器塊,而不需要32位程序的3/4 GB內存限制。這需要一個常規的存儲引擎(NoSQL或SQL)。依靠現有的庫有時是一個好主意和節省時間。 –