2012-03-22 130 views
0

我有一個GUI應用程序,它與點雲數據以及它後面的四叉樹數據結構一起處理數據。由於我正在使用的點格式最近發生了變化,我不得不修改我的點類來保存新的屬性,這會導致Point對象顯着增大,並且實際上會降低我的四叉樹的性能。顯示和處理數據時不需要這些屬性中的一部分,但仍需要將其保存在輸出中。這大約是我的觀點類是如何看的那一刻:將未使用的類數據成員存儲在磁盤上

class Point { 
public: 
    /* ... */ 
private: 
    /* Used data members */ 
    double x; 
    double y; 
    double z; 
    double time; 
    int attr1; 
    int attr2; 

    /* Unused data members */ 
    int atr3; 
    double atr4; 
    float atr5; 
    float atr6; 
    float atr7; 
} 

當數據從點存儲在一個點*數組,然後通過四叉樹處理的文件加載。同樣,當它們被保存時,一系列點將從四叉樹傳遞並保存到文件中。請注意,我在我的四叉樹中使用的Point對象與存儲在文件中的Point對象不同,但我使用的庫提供讀者和寫者對象,我使用它創建點。這裏有一個例子:

int PointLoader::load(int n, Point* points) { 

    Point temp; 
    int pointCounter = 0; 

    /* reader object is provided by the library and declared elsewhere */   
    while (pointCounter < n && reader->read_point()) { 
     temp = Point(reader->get_x(), reader->get_y(), reader->get_z(), /* ... */) 

     points[pointCounter] = temp; 
     ++pointCounter;   
    } 
    return pointCounter; 
} 

現在,我的想法是,以減少Point類的大小和使用的屬性存儲在硬盤上稱爲PointData另一個類(或結構)。這是必要的,因爲數據通常不適合內存,並且存在一個緩存系統,它將再次受益於較小的點對象。因此,給出的例子會是這個樣子:

int PointLoader::load(int n, Point* points) { 

    Point temp; 
    PointData tempData; 
    int pointCounter = 0;  

    while (pointCounter < n && reader->read_point()) { 
     temp = Point(reader->get_x(), reader->get_y(), reader->get_z(), /* ... */) 
     pointData = (reader->get_attr3(), reader->get_attr4(), /* ... */) 

     temp.dataHandle = /* some kind of handle to the data object */ 
     points[pointCounter] = temp; 

     /* Save pointData to file to retrieve when saving points */ 

     ++pointCounter;   
    } 
    return pointCounter; 
} 

後來,當我救我的修改點我會簡單地用dataHandle(文件偏移在內存中的索引映射的陣列?)來檢索每個pointData指向並將其寫回文件。

這聽起來像個好主意嗎?什麼是最明智的做法呢?

回答

1

我建議你使用映射文件來存儲附加數據。如果存在內存壓力,這將自動將它們刷新到磁盤並從RAM中移除,但是如果有足夠的內存,它們大部分時間都會駐留在RAM中。

在您的Point類中,將偏移量存儲在文件中比將直接指針存儲到映射的內存區域更好,因爲如果必須重新映射文​​件才能使其增大,偏移量仍然是正確的(必須增大文件你自己使用例如lseek(),因爲你只能映射文件的大小)。

這種機制編碼起來非常方便,但您必須有足夠的地址空間來映射整個文件 - 在64位應用程序中沒有問題,但如果您是32位並且需要多於一個的問題文件中有幾百MB的數據。您當然可以映射和取消映射多個文件,但它需要更多的編碼工作並且性能較差(對映射和取消映射文件有一定的成本)。

+0

謝謝。要考慮的一件事是,我可以使用int來存儲映射的數組索引,但可能必須使用無符號long long(64位)來存儲偏移量,這又會負面影響Point對象的大小。我正在尋找可能的最有效的解決方案。 – jaho 2012-03-22 14:41:37

+0

@Marian如果對象的大小是固定的,將數組索引存儲到映射區域並使用int而不是基於字節的索引(這將需要很長的時間)沒有問題。這是指針算術的美妙之處。 – 2012-03-22 16:22:59

+0

好的,很酷。我應該使用mmap還是有更多的C++方法來創建內存映射文件? – jaho 2012-03-22 16:59:22