【问题标题】:How can I make a Value Type collection in .NET?如何在 .NET 中创建值类型集合?
【发布时间】:2016-02-13 15:35:56
【问题描述】:

我的应用程序的基本构建块类型分解为一个类型(类或结构),其中包含一些标准值类型(int、bool 等)和一些标准值类型的数组类型,其中会有一个小的 (但未知)集合中的元素数量。

鉴于我有很多上述构建块的实例,我想通过使用数组/集合作为值类型而不是标准引用类型来限制我的基本类型的内存使用。部分问题是我的标准用法是让数组中包含零个、一个或两个元素,并且在这种情况下数组引用类型的开销是令人望而却步的。

我已经根据经验观察并研究证实,数组包装器本身在每个实例中都会引入不需要的(在这种情况下是我)开销。

如何在 .NET 中将集合设为值类型/结构?

旁注:有趣的是,Apple 的 Swift 语言默认将数组作为值类型。

抢先评论

我完全清楚以上是使用 .NET 框架的非标准方式,并且是非常糟糕的做法等......所以没有必要对此发表评论。我真的只是想知道如何实现我的要求。

【问题讨论】:

  • 你想在你的结构中包含值类型数组吗?还是没有数组开销的结构数组?
  • @ThomasBoby 前者是我要问的,但结果也会是后者,因为我的结构中数组的内容本身就是结构。尝试将所有内容保持为结构以避免内存压力。
  • 你不能也不想。为什么以某种方式创建值类型数组会限制内存使用?我倾向于认为相反。

标签: c# .net arrays collections f#


【解决方案1】:

DirectBufferBufferPool 的想法可以混合使用。

如果您使用缓冲池,那么在内存中修复缓冲区并不是什么大问题,因为缓冲区实际上会长期存在,并且不会像在没有缓冲池的情况下修复每个新的 byte[] 那样影响 GC 压缩。

DirectBuffer 使用享元模式并增加了非常少的开销。您可以使用指针直接读/写任何 blittable 结构。据我了解,除了 SBE,Flatbuffers 和 Cup'n Proto 也使用这种方法。在链接的实现中,您应该更改委托,以便它将丢弃的 byte[] 返回到池中。

如果您需要与本机代码互操作或通过网络发送数据,这种解决方案的一大优势是零拷贝。此外,您可以分配单个缓冲区并以类似 ArraySegment 的方式使用偏移量/长度。

更新:

我重新阅读了这个问题,并意识到它专门针对作为值类型的集合。然而,主要理由似乎是内存压力,所以这个答案可能是内存的替代解决方案,即使 DirectBuffer 是一个类。

【讨论】:

    【解决方案2】:

    引用in the docsfixed 关键字似乎就是您要查找的内容。它对类型具有与结构相同的约束,但它确实需要unsafe

     internal unsafe struct MyBuffer
    {
        public fixed char fixedBuffer[128];
    }
    

    如果你还想拥有一个固定的结构数组,那就更复杂了。 fixed 仅支持基值类型,因此您必须手动分配内存。

    【讨论】:

    • 这种解决方案的一个问题是128 或任何其他数字在每个类型定义中都是固定的。要支持任何可变长度之王,您必须分配最大预期长度并浪费大量内存。
    • @V.B.在我看来,如果没有它,实际上不可能有一个带有动态长度列表的结构。结构在内存中具有固定大小,因此您要么有一个固定长度的数组,要么在其外部保留一个指向动态长度数组的指针。这不是解决方案的问题,因为情况不一样。
    猜你喜欢
    • 2020-05-21
    • 1970-01-01
    • 2011-12-05
    • 2015-01-09
    • 1970-01-01
    • 2011-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多