【问题标题】:Why is Span<T>.Length 32 bits instead of 64 bits?为什么 Span<T>.Length 是 32 位而不是 64 位?
【发布时间】:2019-10-25 01:04:14
【问题描述】:

System.Span 的构造函数采用 int 长度,长度在内部存储为 32 位值。

但是,默认填充将使结构的大小无论如何都为 16 字节,因此具有 32 位长度不会节省任何空间。

https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/Span.Fast.cs

Span 设计文档没有提到它。 https://github.com/dotnet/corefxlab/blob/master/docs/specs/span.md

【问题讨论】:

  • 我猜是因为他们不希望您能够在一个跨度内处理超过 20 亿个元素?我的意思是,你最后一次在单个缓冲区中有 > 2 GB 是什么时候?
  • 刚刚,实际上。 :) 我有一个 8gb MemoryMappedFile 并想用 Span 访问它。

标签: .net .net-core


【解决方案1】:

要获得权威答案,您必须询问设计和实现Span&lt;T&gt; 的 .NET 团队。也就是说……

.NET 本质上是一个 32 位框架。它支持 64 位进程,并且可以从 64 位虚拟地址空间进行分配。但它对对象有 2GB 的限制。这导致了另一种设计选择:集合大小是 32 位整数,并且它们是有符号的,因为符合 CLS 的代码不使用无符号值。这两种设计选择相辅相成,相辅相成。

因此,当涉及Span&lt;T&gt; 时,它旨在在托管上下文中提供现有内存的子集,该类型提供的公共接口与 CLS 要求兼容。因此,Length 属性和 indexer 参数都是 32 位整数类型,Span&lt;T&gt; 构造函数的参数在现有内存中指定偏移和长度。

这与 .NET API 的其余部分是一致的,其中数组和其他集合不能超过 2^32 个元素,并且不能大于 2GB。

补充相关阅读:
64-Bit VB.NET Allocating > 2GB of RAM (.NET bug?)
How can I know the ACTUAL maximum number of elements a .net array of a given type can be allocated?
BigArray, getting around the 2GB array size limit

【讨论】:

  • 我明白你所说的关于 CLR 对象的 2GB 限制。在 BigArray 链接中,它建议解决此限制的一种方法是使用本机内存。现在,我们有了一个新模型,可以使用 Span 和 Memory 安全快速地访问本机内存……但在 64 位系统上似乎可以免费使用时,它被限制为 2GB。
【解决方案2】:

问题的答案似乎是 Span 想要匹配具有额外 4 字节字段的 Memory。

https://github.com/dotnet/corefx/issues/26603#issuecomment-370419371

当前版本的 Memory 在 x64 上很好地打包成 16 字节,而 Span 似乎有空间将 int _length 替换为 IntPtr _length 并且仍然适合 8/16 字节。 然而,增加 Span 的 Lenght 属性需要对 Memory 做同样的事情。 如果我没记错的话,增加内存的大小(从 16 字节到 24 字节)可能会对代码的性能产生影响,这会影响到每个人。 (不仅仅是我们这些玩大内存区域的人)

确实,在我介绍的情况下,ReadOnlySequence 可以有效替代启用 64 位的内存/跨度,因为我所需要的只是将数据复制到某处。 但是当您需要在不复制的情况下读取/解码时,API 可能确实不那么简单。 ?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-13
    • 1970-01-01
    • 2011-04-09
    • 2012-12-03
    • 2011-11-05
    • 1970-01-01
    • 1970-01-01
    • 2014-07-31
    相关资源
    最近更新 更多