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

标签 c# caching hashtable memorycache concurrentdictionary

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

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

缓存规范(最大阈值)

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

问题

设置内存缓存、字典、哈希表、数组等的最佳方法是什么,以实现最高效的查找、清除旧缓存数据并防止命中的数据过期。

我看了ASP.Net Cache , System.Runtime.MemoryCache但我认为我需要更轻量级和自定义的东西来实现正确的吞吐量。我也在看 System.Collections.Concurrent作为替代和this related whitepaper .

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

最佳答案

记住,不要过早优化!

可能有一种相当简洁的方法可以做到这一点,而无需诉诸非托管代码、指针等。

在我的旧的普通笔记本电脑上进行的快速测试表明,您可以在 ~100 毫秒内向 HashSet 添加 1,000,000 个条目,同时删除 100,000 个条目。然后,您可以在 ~60 毫秒内使用相同的 1,000,000 个值重复该操作。这仅适用于长整型 - 80 字节数据结构显然更大,但需要一个简单的基准。

我的建议:

  • 将“查找”和“重复检测”作为 HashSet 实现,这对于插入、删除和查找来说速度极快。

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

Circular Buffer for .NET

Fast calculation of min, max, and average of incoming numbers

Generic C# RingBuffer

How would you code an efficient Circular Buffer in Java or C#

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

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

  • 在需要之前避免使用多线程!您有一个自然的“串行”工作负载。除非您知道您的 CPU 线程之一无法处理速度,否则请将其保持在单个线程中。这避免了争用、锁定、CPU 缓存未命中和其他多线程问题,这些问题往往会减慢非 embarrassingly parallel 的工作负载的速度。 .我在这里的主要警告是,您可能希望将事件的“接收”卸载到与处理事件不同的线程。

  • 以上推荐是Staged event-driven architecture (SEDA)背后的主要思想用作高性能和稳定行为的事件驱动系统(例如消息队列)的基础。

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

(注意:如果您需要缓存持久化,请查看Kyoto Cabinet。如果您需要缓存对其他用户可见或分布式,请查看Redis

关于c# - 需要一个高效的内存缓存,每秒可以处理 4k 到 7k 的查找或写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10564181/

相关文章:

C#/WPF - 从父窗口获取子用户控件内的对象

c# - 使用 BackgroundWorker 时出现异常

c# - WCF 服务(NetTcpBinding)+托管 WPF 应用程序

c# - Exe 文件不是从具有数据库连接的 Windows 服务运行?

javascript - 防止在 Angular js应用程序中缓存

ruby - 向 ActiveRecord 模型添加可读的字段描述

javascript - 使用 javascript 找出不同之处

Swift Dictionary 在扩展中使用键访问值

linux - 如何测量多线程应用程序中的缓存性能?

asp.net - 用于 ASP.NET 的缓存管理器应用程序