执行C 代码时快速频繁的文件访问

Fast and frequent file access while executing C++ code

本文关键字:文件 访问 代码 执行      更新时间:2023-10-16

我正在寻找有关如何最好地针对以下要求实现我的代码的建议。在执行我的C 代码期间,我经常需要访问存储在字典中的数据,该字典本身存储在文本文件中。字典包含1亿个条目,在任何时间点,我的代码都会查询与1亿个条目中某些特定条目相对应的数据。没有进行这些查询的特定模式,并且在程序执行的使用寿命中进一步,并非词典中的所有条目都均被查询。此外,该词典在程序的一生中将保持不变。与每个条目相对应的数据并非全部相同的长度。我的字典的文件大小约为24 GB,我只有16 GB的RAM内存。我需要我的应用程序非常快,所以我想知道如何最好地实施这样的系统,以便可以将读取时间最小化。

我也是正在创建字典的人,因此我确实具有将词典分解为较小的数量的灵活性。在考虑我能做什么时,我想到了以下内容,但不确定这两个都很好。

  1. 如果我从文件的开头将每个条目的线路偏移存储在字典中,然后读取相应条目的数据,我可以直接跳到相应的偏移量。有没有办法使用ifstream在不循环的所有线路上进行此操作?在网络上进行快速搜索似乎表明这至少是ifstream的,还有其他方法可以做吗?
  2. 另一个极端想法是为字典中的每个条目创建一个文件,因此我将拥有1亿个文件。这种方法在打开和关闭文件流时具有显而易见的开销缺点。

一般而言,我不相信我想到的任何一种方法都很好,所以我想要一些建议。

,如果您只需要键值访问,并且如果数据大于内存中适合的数据,则答案是NOSQL数据库。这意味着密钥和任意值的哈希类型索引。如果您没有其他限制,例如来自许多客户端的并发访问或扩展可扩展性,则可以自己滚动。自定义NOSQL数据库的最重要问题是预期的键数,它将提供索引文件的大小。您可以在周围找到相当好的哈希算法,并且必须在较大的索引文件和更高的碰撞风险之间做出决定。无论如何,除非您要使用TERA字节索引文件,否则您的代码必须准备好可能发生冲突。

一个详细的解释示例远远超出了我在SO答案中可以写的内容,但它应该给您一个起点。

下一个优化将是应在内存中缓存的。这取决于您期望查询的方式。如果不太可能一次以上的密钥查询,则可能只能依靠OS和文件系统缓存,并且略有改进将是内存映射的文件,否则缓存(索引和/或值(是有意义的。在这里,您可以选择并实现缓存算法。

,或者如果您认为它太复杂而无法获得,则可以搜索一个免费的NOSQL数据库之一可以满足您的要求...

决定使用盘数数据结构后,它就会变得越来越少,而不是系统设计问题。您想实现基于磁盘的字典。从现在开始,您应该考虑以下因素 - 您的磁盘参数是什么?是SSD吗?HDD?您每秒平均查找率是多少?您可以使用20usec -10ms的 Lookup()方法的潜伏期吗?

磁盘词典需要随机磁盘寻求。此类寻求者的SSD延迟数十个微秒,HDD的延迟为3-10ms。同样,您可以秒数有多少此类寻求者有限制。例如,您可以阅读本文。CPU停止成为瓶颈,而IO变得重要。

如果您想追求这个方向 - 有一些最先进的C 库可以为您提供磁带键值商店(不需要流程数据库(,或者您可以自己做一些简单的事情。

如果您的应用程序是批处理过程,而不是服务器/UI程序,即,您还有另一个有限的项目流,您想加入字典,我建议您阅读有关Hash Join或MapReduce(MapReduce(的外部算法。在这些情况下,可以以这样的方式组织您的数据,以至于没有1个巨大的词典为24GB,您可以拥有10个大小为2.4GB的词典,并顺序加载每个字典并加载其中的每个字典并加入。但是为此,我需要了解您要解决的问题。

要总结,您需要在编码解决方案之前先设计系统。使用MMAP或尝试或评论中提到的其他技巧是本地优化(如果有的话(,它们不太可能改变游戏规则。在进行回合计算以了解主要方向之前,我不会急于探索它们。