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



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

为了实现这一目标,我们计划实施multiple read and single writer我们无法更新 g++ 版本,因为我们使用的是g++-4.4

更新:每个工作线程都可以用于读取和写入。如果缺少缓存,则从数据库缓存信息。

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

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

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

  • 读取器写入器锁的性能比较
  • Lib boost devel

问题

  1. boost::shared_mutex是否会影响万一读取频繁时的性能?
  2. 在考虑编译器版本g++4.4时,我们可以采取哪些其他构造和设计方法?
  3. 有没有办法绕过如何设计它,这样reads are lock free

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

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

如果写入极为罕见,您也可以这样做。但是有一些无锁的方式来使线程本地缓存失效,例如每次写入都会更新原子 int,并在这些情况下清除线程本地缓存。

你需要分析它。

如果你因为没有一个可以实际测试东西的"足够相似"的环境而陷入困境,你可能会使用 pthreads 编写一个简单的包装器:pthread_rwlock_t

  • pthread_rwlock_rdlock
  • pthread_rwlock_wrlock
  • pthread_rwlock_unlock

当然,您可以将东西设计为无锁。最明显的解决方案是不共享状态。(如果您确实共享状态,则必须检查目标平台是否支持原子指令)。但是,在对您的应用程序域一无所知的情况下,我觉得非常安全,建议您不要无锁。例如,参见无锁算法真的比完全锁定算法的性能更好吗?

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

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

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

  3. 具有
  4. 小更新的大缓存或具有 RCU 频繁更新的大缓存读写锁是一个不错的选择。

除了建议你分析它的其他答案外,如果你能以某种方式构建或预测请求的类型、顺序和大小,就会有很大的好处。

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

  • 同样,在选择更新方法时,请求的大小也很重要。较小的数据片段可以存储更长时间,甚至可以汇集在一起,而较大的数据片段的请求频率可能较低。

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

相关内容

  • 没有找到相关文章

最新更新