我需要在大约1k块的磁盘上存储大量数据。我将以难以预测的方式访问这些对象,但可能存在模式。
我是否可以使用根据我的访问模式重新排列磁盘上的对象以尝试最大化顺序访问,从而最大限度地减少磁盘搜索时间?
答案 0 :(得分:4)
在现代操作系统(Windows,Linux等)上,您无法做任何事情来优化寻道时间!原因如下:
要解释Raymond Chen,如果您不得不询问操作系统限制,那么您可能做错了什么。将您的文件系统视为一个不可变的黑盒子,它就是它(我知道,您可以使用RAID等帮助)。
您必须采取的第一步(必须在优化时采取)是衡量您目前所拥有的。永远不要假设。使用硬数据验证所有内容。
从你的帖子中,听起来你还没有真正编写任何代码,或者,如果你有,那么目前没有性能问题。
唯一真正的解决方案是查看更大的图片并开发方法从磁盘上获取数据而不会拖延应用程序。这通常是通过异步访问和推测加载。如果您的应用程序始终访问磁盘并使用较小的数据子集,您可能需要考虑重新组织数据,将所有有用的东西放在一个地方,将其他数据放在其他地方。如果不了解完整的问题域,就不可能真正有用。
答案 1 :(得分:2)
根据“难以预测”的含义,我可以考虑几个选项:
如果您始终基于相同的块字段/属性进行搜索,请将记录存储在按该字段排序的磁盘上。这使您可以使用binary search来提高O(log n)效率。
如果您在不同的块字段上搜索,请考虑为每个字段存储外部索引。 b-tree为您提供O(log n)效率。当你寻找时,抓住适当的索引,搜索你的块的数据文件地址并跳转到它。
更好的是,如果您的块是同构的,请考虑将它们分解为数据库记录。数据库为您提供优化的存储,索引以及免费执行高级查询的能力。
答案 2 :(得分:1)
解决这个问题的最简单方法是使用一个操作系统来解决这个问题,比如Linux。给它足够的RAM来容纳10%的RAM中的对象,它会尽可能地将高速缓存中的对象保留在缓存中,将加载时间减少到0.最近的 server 版本的Windows可能会工作(也有一些不适合我,这就是为什么我提到这个)。
如果这是不行,请尝试此算法:
在硬盘上创建一个非常大的文件。一次性写入这一点非常重要,因此操作系统将在磁盘上分配连续的空间。
将所有对象写入该文件。确保每个对象的大小相同(或者在文件中为每个对象提供相同的空间,并记下每个块的前几个字节中的长度)。使用空硬盘或刚刚进行了碎片整理的磁盘。
在数据结构中,保留每个数据块的偏移量以及访问频率。当经常访问它时,将其在文件中的位置与一个更接近文件开头且访问次数较少的块交换。
[编辑]使用操作系统的内存映射API访问此文件,以允许操作系统有效地缓存最常用的部分,以获得最佳性能,直到您下次可以优化文件布局。
随着时间的推移,大量访问的块会冒泡到顶部。请注意,您可以在一段时间内收集访问模式,分析它们,并在机器负载很小的情况下重新排序。或者你可以在完全不同的机器上进行重新排序,并在完成后交换文件(和偏移表)。
那就是说,你应该真正依赖现代操作系统,很多聪明的人都认为很长很难以为你解决这些问题。
答案 3 :(得分:1)
使用内存映射文件访问而不是通常的open-seek-read / write模式。这种技术适用于Windows和Unix平台。
通过这种方式,操作系统的虚拟内存系统将为您处理缓存。访问已经在内存中的块将导致无磁盘搜索或读取时间。从内存写回磁盘可以自动有效地处理,而不会阻止您的应用程序。
Aaron的笔记也很好,因为它们会影响一个不在内存中的块的初始加载时间。将其与内存映射技术相结合 - 毕竟使用memcpy()
重新排序块比从磁盘读取/写入并尝试交换等更容易。
答案 4 :(得分:0)
这是一个有趣的挑战。不幸的是,我也不知道如何解决这个问题。 Corbin的做法对我来说听起来很合理。
这里有一点优化建议,至少:将访问量最大的项目放在磁盘的中心(或未分段文件),而不是在开头。这样,寻求较少使用的数据将更接近平均值。呃,这很明显。
如果您自己找到解决方案,请告诉我们。