c++ - 将未使用的类数据成员存储在磁盘上

标签 c++ performance class file-io point-clouds

我有一个 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 对象与存储在文件中的对象不同,但我使用的库提供了我用来创建点的读取器和写入器对象。这是一个例子:

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;
}

然后,当我保存修改后的点时,我只需使用数据句柄(文件偏移量?内存映射数组中的索引?)检索每个点的点数据并将其写回文件。

这听起来是个好主意吗?实现这一目标最明智的方法是什么?

最佳答案

我建议您使用映射文件来存储附加数据。如果存在内存压力,这将自动将它们刷新到磁盘并从 RAM 中删除,但如果有足够的内存,它们将大部分时间驻留在 RAM 中。

在您的 Point 类中,将偏移量存储在文件中比将直接指针存储到映射的内存区域更好,因为如果您必须重新映射文​​件以增加它,偏移量仍然是正确的(您必须自己使用例如 lseek() 来增大文件,因为您只能映射文件的大小)。

这种机制编写代码非常方便,但您必须有足够的地址空间来映射整个文件 - 在 64 位应用程序中没有问题,但如果您是 32 位应用程序并且需要多个文件中有几百 MB 的数据。您当然可以映射和取消映射多个文件,但它需要更多的编码工作并且性能较低(映射和取消映射文件会产生一些成本)。

关于c++ - 将未使用的类数据成员存储在磁盘上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9822466/

相关文章:

objective-c - 有没有办法在 Objective-C 上动态解析类方法?

C++类继承变量

c++ - 如何在 C++ 中获取有关物理网络适配器的信息

sql - 为什么 MongoDB 比 SQL DB 快得多的任何详细和具体原因?

java - String 和 HashSet 之间用于检查重复项的最佳(性能 + 内存)是什么

python - 如何从解释器堆栈中获取绑定(bind)方法的类名?

c++ - 类成员函数的 GSL 集成

c++ - 获取 C++ 函数参数的类型

c++ - 为什么不将临时对象传递给另一个线程会导致未定义的行为?

mysql - MariaDB 中的 TokuDB 性能