如何LRU缓存大量由C++STL重结构组成的对象

How to LRU-cache numerous objects made of C++ STL heavy structures?

本文关键字:结构 对象 C++STL 缓存 LRU 如何      更新时间:2023-10-16

我有一个大的C++/STL数据结构(myStructType),其中包含叠瓦列表和映射。我有很多这种类型的对象,我想用一个键LRU缓存。我可以在需要时从磁盘重新加载对象。此外,它必须在BSD平台上运行的多处理高性能应用程序中共享。

我可以看到几个解决方案:

  1. 我可以考虑一个pair<size_t lifeTime, myStructType v>的终身排序列表,再加上一个o(1)从其键访问列表中所需对象的索引的映射,我可以使用shm和mmap来存储所有内容,并使用一个锁来管理访问(参见此处)
  2. 我可以使用为LRU配置的redis服务器,并重新设计我的数据结构,以redis键/值和键/列表对
  3. 我可以使用为LRU配置的redis服务器,并串行化我的数据结构(myStructType),以便使用redis管理一个简单的键/值

当然,可能还有其他解决方案。你会如何做到这一点,或者更好的是,你是如何成功做到的,记住高性能?

此外,我希望避免像Boost这样的严重依赖关系。

我最近实际上构建了缓存(不仅仅是LRU)。

选项2和3很可能不会比从磁盘重新读取快。实际上根本没有缓存。此外,这将是一个比Boost更严重的依赖。

选项1可能具有挑战性。例如,您建议使用"锁"。这将是一个相当争用的锁,因为它必须保护每个生命周期更新,以及所有LRU操作。由于您的对象已经很重,因此为每个对象设置一个唯一的锁可能是值得的。该解决方案有一些中间变体,其中有多个锁,但每个锁也有多个对象。(你仍然需要一把钥匙来保护整个地图,但这只是为了更换)

您还可以考虑是否确实需要严格的LRU。该策略假设对象被重用的机会会随着时间的推移而减少。如果事实并非如此,那么随机替换也同样好。您还可以考虑一次驱逐多个元素。其中一个挑战是,当一个元素需要删除时,所有线程都会删除,但如果一个线程删除它就足够了。这就是为什么批量删除有帮助:如果一个进程试图获取锁进行批量删除,但失败了,它可以在假设缓存很快就会有可用空间的情况下继续。

一个快速的胜利是不更新最后使用的元件的LRU时间。它已经是最新的了,再更新也无济于事。当然,只有当你经常再次快速使用该元素时,这才会产生效果,但(如上所述)否则你只会使用随机驱逐。