【问题标题】:Lock-free Shared Memory in C++ for Variable length RecordsC++ 中用于可变长度记录的无锁共享内存
【发布时间】:2012-02-25 04:49:19
【问题描述】:

我是 IPC 的新手。 Writer进程将数据写入共享内存,许多Reader进程读取数据。要写入的数据具有唯一标识符,必须通过唯一键索引以便更快地访问(例如 STL::map 或 hashmap 用于查找)。数据也是可变长度记录( XML )(平均长度为 200-250 字节)。操作系统是 Intel Xeon 四核服务器上的 solaris 10 (i86pc)。

总数据量超过200G。但我们将只在共享内存中保留最新数据。历史数据驻留在文件中。共享内存大小约为 4G~6G。

没有可用的外部库,如 Boost::interprocess

我有几个问题,可能很多

  1. 哪个更高效:shared_memory 或 mmap(内存映射文件)
  2. 如何为可变长度记录建立索引。 [我不知道,可能是一些散列?]。
  3. 如果将 XML 转换为固定大小的结构,这会不会很整洁(权衡 - 结构的大小会很大,将近 300 多个可能的字段)
  4. 我们可以通过提供自定义分配器将任何 STL 放入 shared_memory 中吗?
  5. 是否可以在没有信号量的情况下实现(使用 CAS 的无锁实现)。

谢谢

这个怎么样。

|--------------------------|
| start_id   |   end_id    |   ->  range of msg id present in the segment
|--------------------------|
| id1 | start_mem | length |   ->
|--------------------------|   ->
| id2 | start_mem | length |   -> table of index for the actual data
|--------------------------|   ->
| id3 | start_mem | length |   ->
|--------------------------|   ->
| id4 | start_mem | length |   ->
|--------------------------|   ->
|                          |
|                          |
|                          |
|       data segment       |
|       varibale length    |
|       xml are stored     |
|                          |
|                          |
|--------------------------|

当新数据到达并且段已满时。最旧的数据以循环方式擦除。可能需要删除 1 条以上的记录。

【问题讨论】:

  • 你用的是什么编译器?
  • 请用你的标题描述问题。实际上,在我们讨论它的同时,这是 五个 问题。像这样发布它们。
  • 您的读者是否必须阅读相同的数据?所有进程的键数是否固定?
  • 是的,所有读者都必须阅读相同的数据。但是有些可能会更快消耗,有些可能会因为阅读器对数据进行的某些操作而稍慢一些。 (这些操作因读者而异)
  • 您的索引要求是什么?

标签: c++ ipc semaphore shared-memory copy-and-swap


【解决方案1】:

最简单的解决方案,如果您需要复杂的索引和其他类似的东西,您应该真正考虑面向服务的架构而不是共享内存。只需指定一个进程作为您的主缓存进程,并让它接受来自需要数据的其他进程的本地连接(通过 unix 域套接字或 TCP 套接字或其他)。这让事情变得非常简单。

如果您不选择这条路线,请注意共享内存是hard。您所要求的在共享内存中绝对是可行的 - 您可以在这个 shmem 块中创建一个堆分配器,等等。STL 分配器可能工作,但不要指望任何第三方库对此感到满意使用自定义指针类型的 STL 分配器。你需要锁(如果你很聪明,你可能在某些情况下可以避免它们,但不是全部,在这种情况下肯定要和 STL 说再见),你将不得不重建一切你通常认为是理所当然的。

再次,我强烈建议您从一个简单的缓存守护程序开始。这在大多数情况下都可以很好地扩展,只是增加了一点延迟。

【讨论】:

  • 作为即时解决方案,SOA 架构是不可能的。发布这个问题后,我知道我们不能在 shared_memory 中放置任何 STL(它使用其他进程不可见的指针)
  • 在您的情况下为什么不能使用主进程?
  • 为了其他人寻求解决方案,请回答问题
【解决方案2】:

是否可以在没有信号量的情况下实现(使用 CAS 的无锁实现)。

由于无锁(无锁)实现很难设计,而且我们最终可能会陷入混乱,因此在采用无锁解决方案之前,您应该考虑以下方面和替代方案:

  • 如果系统中有很多线程,那么调度器很可能会抢占持有锁的线程,因此所有其他线程都将等待锁(如果不是无锁不会带来显着改善) .
  • 如果这可以使用读写锁解决。 (作者远少于读者)。
  • 如果锁争用的可能性较小,那么您可能会考虑使用自旋锁,这将为您提供与无锁相同的性能。

【讨论】:

  • 为了其他人寻求解决方案,请回答问题
猜你喜欢
  • 2012-10-16
  • 1970-01-01
  • 2014-04-08
  • 1970-01-01
  • 2012-08-31
  • 2015-07-23
  • 1970-01-01
  • 1970-01-01
  • 2017-10-25
相关资源
最近更新 更多