需要一个高效的内存缓存,每秒可以处理4k到7k的查找或写入

goo*_*ate 11 c# caching hashtable memorycache concurrentdictionary

我有一个高效的C#应用​​程序,它在多线程CPU上以每秒5k到10k记录的速率接收80字节的数据.

我现在需要设置一个内存缓存来检测和过滤重复记录,这样我就可以抑制它们在管道中进一步移动.

缓存规格(最大阈值)

  • 80字节的数据
  • 10,000记录/秒
  • 60秒的缓存=密钥数量= 60,000
  • (子总数48000000字节= 48Mb)
  • 理想缓存大小= 5分钟(或240Mb)
  • 可接受的运行时缓存大小膨胀= 1 GB

设置内存缓存,字典,哈希表,数组等的最佳方法是什么,它将允许最有效的查找,清除旧的缓存数据,并防止被击中的数据到期.

我查看了ASP.Net Cache,System.Runtime.MemoryCache,但我认为我需要一些更轻量级的东西来定制以获得正确的吞吐量.我也在看System.Collections.Concurrent作为替代和相关的白皮书.

有没有人对最佳方法有什么建议?

yam*_*men 9

记住,不要过早优化!

在不诉诸非托管代码,指针等的情况下,可能有一种相当简洁的方法.

对我旧的普通笔记本电脑进行快速测试表明,您可以添加1,000,000个条目,HashSet同时在~100ms内删除100,000个条目.然后,您可以在~60ms内使用相同的1,000,000个值重复该值.这适用于长期工作 - 80字节的数据结构显然更大,但是一个简单的基准测试是有序的.

我的建议:

  • 实现'查找'和'重复检测'作为一个HashSet,这对于插入,删除和查找非常快.

  • 实现实际缓冲区(接收新事件并使旧事件过期)作为适当大的循环/环形缓冲区.这将避免内存分配和解除分配,并可以在前面添加条目并从后面删除它们.以下是一些有用的链接,包括一个(第二个),它描述了缓存中的项目到期的算法:

.NET的循环缓冲区

快速计算传入数字的最小值,最大值和平均值

通用C#RingBuffer

您将如何使用Java或C#编写高效的循环缓冲区?

  • 请注意,如果您希望缓存受元素数量(例如100,000)而不是事件时间(比如最后5分钟)限制,则循环缓冲区会更好.

  • 当从缓冲区中删除项目(首先从末尾搜索)时,也可以从缓冲区中删除它们HashSet.无需使两个数据结构相同.

  • 在您需要之前避免多线程!你有一个自然的"连续"工作量.除非您知道某个CPU线程无法处理速度,否则请将其保存在单个线程中.这可以避免争用,锁定,CPU缓存未命中以及其他多线程问题,这些问题往往会减慢非常难以并行的工作负载.我的主要警告是,您可能希望将事件的"接收"卸载到与处理它们不同的线程中.

  • 上述建议是分阶段事件驱动架构(SEDA)背后的主要思想,它被用作高性能和稳定行为事件驱动系统(如消息队列)的基础.

上述设计可以干净地包装,并尝试以最小的复杂性实现所需的原始性能.这仅提供了一个合适的基线,现在可以从中提取和测量效率.

(注意:如果您需要缓存的持久性,请查看Kyoto Cabinet.如果您需要缓存对其他用户可见或分发,请查看Redis.