2011-11-17 70 views
3

這已經有一段時間,因爲我做任何C++,我的最佳方式有點生疏實現以下:如何創建C的內存映射列表++對象

我們有一個數據庫,該數據庫存儲大量的「對象」。我試圖想辦法將這些對象的整個列表加載到內存中,但由於這些對象的大小和數量,將它們全部放在內存中是不切實際的。相反,我希望有一個「內存映射文件」的系統,在訪問對象時按需加載對象。換句話說,讓操作系統或類似的東西管理哪些對象應該在內存中,類似於操作系統如何決定應該將哪個段的文件分頁到內存中。任何人都可以給.me提示如何做到這一點?

+0

什麼操作系統您使用的? –

+0

如果你在Windows上,看看'CreateFile()','CreateFileMapping()'和'MapViewOfFile()'函數。 –

+0

嗨,對不起,忘了提及我正在使用FreeBSD,但是想把它移植到任何* nix平臺上 – esotechnica

回答

0

因此,根據對象的大小,您可以將它們存儲在哈希映射中,該映射保留LRU列表並開始將對象驅逐到文件中,同時保持映射中的鍵和文件偏移量。這樣,當你需要從磁盤中取出它時,只需一次搜索和一次讀取就可以取回對象。如果您想要預先分配固定大小的文件,您可以將它們映射,並且您的偏移量將成爲另一個指針。

這是對Riak數據庫初始存儲如何工作的簡化,他們在其網站上有一些設計文檔[1] [2]。如果你的對象比關鍵字大,這樣只有所有的關鍵字都能很容易地嵌入內存中,而對象則不能。

卡桑德拉數據庫使用類似的技術,其「密鑰緩存」[3]。

你也可以看看像Berkly DB您當地的商店

[1]:http://wiki.basho.com/Concepts.html#Data-Storage
[2]:http://downloads.basho.com/papers/bitcask-intro.pdf
[3]:http://www.datastax.com/dev/blog/maximizing-cache-benefit-with-cassandra

+0

真棒,這是我想到的那種事,歡呼! – esotechnica

1

如果你在C++上生鏽,你可以採取一個簡單的方法。

您提到「物體」;我把它當作「用戶數據」而不是實際的序列化C++類。

無論如何,內存映射文件只是一個文件。你將從文件中讀取,操作系統不會爲你解決你的問題。

我的建議是保持簡單。實現你的「對象」作爲一個普通的文件I/O。然後,一旦你有這個工作,你可以通過使用內存映射文件來改善性能。

至於設計模式, 我將設計一個由CDataBase類創建的CObject類。 CDataBase會知道文件(數據庫)中的每個對象的位置,然後根據需要創建CObjects(從文件中讀取它們)。

祝你好運。

+0

嗨,謝謝你的迴應。當我說'內存映射文件'時,我並不是真正的意思,我只是用這個比喻來描述我想要做的事情。是的,當我說'對象'時,我的意思是存儲在SQL表中的數據,所以我不能真正使用基於文件的方法 – esotechnica

1

只是一個警告 - 如果你有大量的對象存儲在SQL表中,你想任意加載到內存中,它可能會以多種方式緩慢:很多命中數據庫(嘗試使用最小數量的查詢),太多的構造函數調用(使用內存池)等...

...但你需要一步一步 - 看看你是否可以從SQL讀入一個實例化對象的記錄。最佳的速度優化將在於如何組織數據以最小化對數據庫的命中並最小化構造函數調用。

請注意,內存映射解決方案將代替SQL表 - 它將比SQL更快但靈活性更低,並且您將遇到雙重維護的麻煩:SQL中的數據必須保持同步與您的內存映射文件。

+0

嗨,這正是我所關心的。基本上,我只想創建一個對象一次(即將數據從數據庫讀取到對象的相應成員中)。然後,類似於最近未使用的內存頁面如何寫入後臺存儲,我想以某種方式對這些對象執行相同的操作。這樣,如果一個對象被「換出」到一個磁盤文件中,它所需要做的就是從磁盤讀取該對象的二進制表示並指向它。這可以避免從SQL重新加載對象的開銷緩慢等。也許它不可能/容易做到? – esotechnica