内存中 Boost r-tree 与映射文件的性能差异
Performance difference of Boost r-tree in memory vs. mapped file
我需要创建一个 3D R*-tree,也许是为了长期存储,但性能也是一个问题。
为了创建树,我决定使用Boost的spacialindex,基本上找到了两种可能的方法。
要么我直接使用对象创建它,因为它在这里:Index of polygons stored in vector,但是这不允许我在不再次创建 R* 树的情况下存储和加载它。
或者我可以使用此处解释的映射文件:Index stored in mapped file using Boost.Interprocess,但是,我不确定在这种情况下查询的性能是否足够好。
我的 r-tree 将包含几千个条目,但很可能少于大约 100,000 个。现在我的问题是,与使用标准对象相比,使用映射文件是否存在任何严重的性能问题?此外,如果创建一个包含大约 100,000 个值的 R* 树不需要花费大量时间(我可以将所有边界框和相应的 keys/data 存储在一个文件中),那么它可能是一个更好的选择跳过映射文件,每次我 运行 程序时只创建树?
希望有人能在这里帮助我,因为文档并没有真正提供太多信息(尽管它仍然比 libspacialindex 的文档好很多)。
映射文件的行为与常规内存很相似(事实上,在 Linux 中,使用 new
或 malloc
的内存分配将使用 mmap
[带有 "no file"后备存储]作为底层分配方式)。但是,如果您执行许多小写操作 "all over the place",并且您映射的是真实文件,那么 OS 将在写入文件之前限制缓冲写入的数量。
前一段时间出现这个问题时我做了一些实验,通过调整 OS 如何处理这些 "pending writes" 的设置,即使是文件备份内存映射,我也获得了合理的性能随机 read/write 模式 [我希望在您构建树时发生的事情]。
这是 "performance of mmap with random writes" 的问题,我认为它是高度相关的:
Bad Linux Memory Mapped File Performance with Random Access C++ & Python
(此答案适用于 Linux - 其他 OS,尤其是 Windows,在处理写入映射文件的方式方面可能表现完全不同)
当然,很难说 "which is better",在内存映射文件或每次程序重建之间 运行 - 这真的取决于你的应用程序做什么,你是否 运行 每秒 100 次,或每天一次,重建需要多长时间 [我完全不知道!],以及许多其他类似的事情。有两种选择:构建最简单的版本,看看它是否是 "fast enough",或者构建两个版本,并测量有多少差异,然后决定走哪条路。
我倾向于构建简单的(大概)模型,如果性能不够好,找出缓慢的原因,然后修复它 - 它可以节省花费大量时间来制作需要 0.01% 的东西总执行时间的 运行 快了 5 个时钟周期,并且在其他地方得到了一个很大的思考,这使得它 运行 比您预期的慢 500 倍...
批量加载索引 比重复插入快 很多,并且生成效率更高的树。因此,如果您可以将所有数据保存在主内存中,我建议使用 STR 批量加载重建树。根据我的经验,这已经足够快了(批量加载时间与 I/O 时间相比相形见绌)。
STR的成本大致就是排序的成本。 O(n log n)
理论上,常量非常低(效率较低的实现可能是 O(n log n log n)
,但仍然相当便宜)。
我需要创建一个 3D R*-tree,也许是为了长期存储,但性能也是一个问题。 为了创建树,我决定使用Boost的spacialindex,基本上找到了两种可能的方法。
要么我直接使用对象创建它,因为它在这里:Index of polygons stored in vector,但是这不允许我在不再次创建 R* 树的情况下存储和加载它。
或者我可以使用此处解释的映射文件:Index stored in mapped file using Boost.Interprocess,但是,我不确定在这种情况下查询的性能是否足够好。
我的 r-tree 将包含几千个条目,但很可能少于大约 100,000 个。现在我的问题是,与使用标准对象相比,使用映射文件是否存在任何严重的性能问题?此外,如果创建一个包含大约 100,000 个值的 R* 树不需要花费大量时间(我可以将所有边界框和相应的 keys/data 存储在一个文件中),那么它可能是一个更好的选择跳过映射文件,每次我 运行 程序时只创建树?
希望有人能在这里帮助我,因为文档并没有真正提供太多信息(尽管它仍然比 libspacialindex 的文档好很多)。
映射文件的行为与常规内存很相似(事实上,在 Linux 中,使用 new
或 malloc
的内存分配将使用 mmap
[带有 "no file"后备存储]作为底层分配方式)。但是,如果您执行许多小写操作 "all over the place",并且您映射的是真实文件,那么 OS 将在写入文件之前限制缓冲写入的数量。
前一段时间出现这个问题时我做了一些实验,通过调整 OS 如何处理这些 "pending writes" 的设置,即使是文件备份内存映射,我也获得了合理的性能随机 read/write 模式 [我希望在您构建树时发生的事情]。
这是 "performance of mmap with random writes" 的问题,我认为它是高度相关的: Bad Linux Memory Mapped File Performance with Random Access C++ & Python (此答案适用于 Linux - 其他 OS,尤其是 Windows,在处理写入映射文件的方式方面可能表现完全不同)
当然,很难说 "which is better",在内存映射文件或每次程序重建之间 运行 - 这真的取决于你的应用程序做什么,你是否 运行 每秒 100 次,或每天一次,重建需要多长时间 [我完全不知道!],以及许多其他类似的事情。有两种选择:构建最简单的版本,看看它是否是 "fast enough",或者构建两个版本,并测量有多少差异,然后决定走哪条路。
我倾向于构建简单的(大概)模型,如果性能不够好,找出缓慢的原因,然后修复它 - 它可以节省花费大量时间来制作需要 0.01% 的东西总执行时间的 运行 快了 5 个时钟周期,并且在其他地方得到了一个很大的思考,这使得它 运行 比您预期的慢 500 倍...
批量加载索引 比重复插入快 很多,并且生成效率更高的树。因此,如果您可以将所有数据保存在主内存中,我建议使用 STR 批量加载重建树。根据我的经验,这已经足够快了(批量加载时间与 I/O 时间相比相形见绌)。
STR的成本大致就是排序的成本。 O(n log n)
理论上,常量非常低(效率较低的实现可能是 O(n log n log n)
,但仍然相当便宜)。