不断增长的固定容量通用序列的最佳选择

RPM*_*984 5 .net c# sequences

我试图在 .NET 缓存中保留内存中的条目列表,代表对我的应用程序的最后 N 个 HTTP 请求。为此使用的最佳 .NET 序列是什么?

要求

  • 固定数量的项目(例如 50)
  • 可序列化(需要将序列添加到.NET缓存)
  • 当我尝试添加 max+1 条目时,它会自动删除最旧的项目以腾出空间
  • 不太关心项目的顺序
  • 需要能够在单个操作中获取所有项目,以便执行聚合计算。
  • 线程安全
  • 非唯一(例如List<T>、 not Dictionary<TKey,TValue>)。我可能会点击 URL /foo10 次,这不是唯一的,但所有内容都需要添加到序列中。

我突然想到我可以使用 a Queue<T>,在排队时只需检查长度,如果达到容量,则将旧的出队。但担心线程安全(ConcurrentQueue<T>也许?)和最佳方法,因为这是我的应用程序的“热门”区域,需要优化。

谢谢!

Nig*_*888 4

这实际上取决于您所说的“最旧的条目”的具体含义。

如果您正在寻找 FIFO 结构,则可以扩展以ConcurrentQueue<T>弹出最旧的项目(输入的第一个项目)。(从这个答案复制)。

public class FixedSizedQueue<T> : ConcurrentQueue<T>
{
    private readonly object syncObject = new object();

    public int Size { get; private set; }

    public FixedSizedQueue(int size)
    {
        Size = size;
    }

    public new void Enqueue(T obj)
    {
        base.Enqueue(obj);
        lock (syncObject)
        {
            while (base.Count > Size)
            {
                T outObj;
                base.TryDequeue(out outObj);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您正在寻找一个缓存来跟踪最后一项被访问的时间,并弹出最近最少访问的一项(有点像 System.Runtime.Caching 中的滑动过期功能),您可以使用最近最少使用的(LRU)缓存

CSharpTest.Net.Collections项目中有一个名为LurchTable的高性能线程安全 .NET 实现,可在 NuGet 上获取

引入 LurchTable 作为 LinkedHashMap 的 C# 版本

对于其他选项,请参见

  • 如果该类被强制转换为任何其他类型,它将无法正常运行,我在使用“public new void Enqueue(T obj)”时会稍微小心一些。我会选择组合而不是继承。创建一个实现“IProducerConsumerCollection&lt;T&gt;”的新类,并让它包含一个“ConcurrentQueue&lt;T&gt;”作为私有成员,它将所有调用转发到该私有成员。 (2认同)