通过 boost::shared_mutex 在 g++-4.4(不在 C++11/14 中)中实现多个 reader 单个编写器是否会影响性能?

Does Multiple reader single writer implementation in g++-4.4(Not in C++11/14) via boost::shared_mutex impact performance?

用法: 在我们的产品中,我们有大约 100 个线程可以访问我们试图实现的缓存。如果缓存丢失,则将从数据库中获取信息并通过编写器线程更新缓存。

为此,我们计划实施 multiple read and single writer 我们无法更新 g++ 版本,因为我们正在使用 g++-4.4

Update: Each worker thread can work for both read and write. If cache is missed then information is cached from the DB.

问题陈述: 我们需要实现缓存来提高性能。 为此,缓存读取更频繁,对缓存的写入操作要少得多。

我想我们可以使用 boost::shared_mutex boost::shared_lockboost::upgrade_lockboost::upgrade_to_unique_lock implementation

但我们了解到 boost::shared_mutex 存在性能问题:

问题

  1. 如果读取非常频繁,boost::shared_mutex 是否会影响性能?
  2. 在考虑编译器版本 g++4.4 时,我们可以采用哪些其他构造和设计方法?
  3. 是否有设计方法,例如reads are lock free

此外,我们打算使用Map来为缓存保留信息。

您需要对其进行分析。

如果您因为没有 "similar enough" 可以实际测试东西的环境而陷入困境,您可以使用 pthreads 编写一个简单的包装器:pthread_rwlock_t

  • pthread_rwlock_rdlock
  • pthread_rwlock_wrlock
  • pthread_rwlock_unlock

当然你可以把东西设计成无锁的。最明显的解决方案是 不共享状态 。 (如果您确实共享状态,则必须检查您的目标平台是否支持原子指令)。但是,在不了解您的应用程序域的情况下,我非常有把握地建议您不要 想要无锁。参见例如Do lock-free algorithms really perform better than their lock-full counterparts?

如果写入不存在,一种可能性是2-level cache,您首先有一个thread-local cache,然后是normal cache with mutex or reader/writer lock .

如果写入极少,你也可以这样做。但是 有一些使线程局部缓存无效的无锁方法 ,例如每次写入都会更新一个原子整数,在这些情况下会清除线程本地缓存。

这完全取决于更新的频率、缓存的大小以及更新中更改了多少。

  1. 假设您有一个相当大的缓存,每次更新都会有很多更改。然后我会使用无锁的读取-复制-更新模式。

  2. 如果你的缓存数据非常小且一次性读取(例如单个整数),RCU 也是一个不错的选择。

  3. 大缓存,小更新或大缓存,更新对于 RCU 来说是频繁的读写锁是一个不错的选择。

除了建议您对其进行概要分析的其他答案外,如果您能够以某种方式构造或预测请求的类型、顺序和大小,将会带来很大的好处。

  • 如果在典型周期中请求特定类型的数据,最好按数据类型拆分缓存。您将增加 cache-hit/miss 比率,并且每个缓存的大小都可以适应该类型。您还将减少可能的争用。

  • 同样,在选择更新方法时,请求的大小也很重要。较小的数据片段可能会存储更长时间甚至汇集在一起​​,而较大的数据块可能不会那么频繁地被请求。

  • 即使有了只涵盖最频繁提取模式的基本预测方案,您也可能已经大大提高了性能。尝试和训练是绝对值得的,例如一个NN(神经网络)来提前猜测下一个请求。