我有一个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;
}
当从文件加载数据时,Points存储在Point *数组中,然后由quadtree处理。类似地,当它们被保存时,从四叉树传递点数组并保存到文件中。请注意,我在四叉树中使用的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并将其写回文件。
这听起来像个好主意吗?实现这一目标最明智的方法是什么?
答案 0 :(得分:1)
我建议您使用映射文件来存储其他数据。如果有内存压力,这将自动将它们刷新到磁盘并从RAM中删除,但如果有足够的内存,它们将在大多数时间内驻留在RAM中。
在你的Point
类中,在文件中存储偏移量比将直接指针存储到映射的内存区域更好,因为如果你必须重新映射文件以便增长它,那么偏移量仍然是正确的(你必须使用例如lseek()
自己增长文件,因为你只能映射文件的大小。)
这种机制对代码来说非常方便,但你必须有足够的地址空间来映射整个文件 - 在64位应用程序中没有问题,但如果你是32位并且需要的不仅仅是一个问题,那么可能会出现问题文件中有几百MB的数据。您当然可以映射和取消映射多个文件,但它需要更多的编码工作并且性能较差(映射和取消映射文件需要一些成本)。