了解ReadOnlyMemory中发现的奇怪代码<T>

问题描述 投票:0回答:1

我使用 IL 反汇编程序查看了 ReadOnlyMemory 结构体 (.NET 461) 的 Length 属性的代码,发现了这个奇怪的代码:

public int Length => this._length & int.MaxValue;

这里与 int.MaxValue 进行 AND 运算的原因是什么?

c# .net performance disassembly
1个回答
0
投票

(此答案仅与 System.Memory.dll

 的当前最新版本
专门用于 .NET Framework 4.x ,而不是 .NET Core 和 .NET 5+ 附带的版本)

(作为style的免责声明:我看到Memory<T>

的作者选择使用下划线前缀作为状态字段名称 - 这不是我自己会做的事情 - 我只是逐字使用他们的字段名称为了清楚起见)

顺便说一句,

Memory<T>

ReadOnlyMemory<T>
具有相同的布局 - 唯一的区别在于它们暴露的界面设计,所以我在这里互换使用术语
ReadOnlyMemory<T>
Memory<T>


  • Memory<T>
    类型是一种需要轻量级的
    struct
    类型,这意味着它不能拥有超过绝对必要的字段:
    
      它需要一个指向实际内存目标的指针(严格来说,一个
    • 对象引用),例如字节数组缓冲区或其他什么。
      • Memory<T>
         中,这由名为 
        Object
         的不透明 
        _object
         字段表示,因为它不仅可以表示 
        Byte[]
        ,还可以表示 
        Char[]
        String
        Span<T> 的任何其他类型 可以合作。
        
        
      它需要一个
    • Int32 _length
    • 字段来存储它指向的内存区域/缓冲区的长度。
      .NET 每个对象的实际限制为 2GiB,因此也没有必要这样做 
        Int64
      • (这样做也会消耗 2 倍以上的存储空间)。
        
        
      它还需要一个
    • Int32 index
    • 字段来存储其当前读/写“头”
      into
    因此,这意味着
  • Memory<T>
  • (如果内存中的
    packed
    )已经消耗了 x86 上的 32 + 32 + 32 = 96 bytes,或者 x64 上的
    64 + 32 + 32 = 128 bytes
    struct` 可以变成。
    ...但肯定 
    - which is pushing at the limit for how big a
    还需要存储有关
  • Memory<T>
  • 的确切
    type
    的信息,否则在执行 之前需要依赖(非常昂贵的)运行时类型测试(例如 _object
     运算符)任何行为都会对性能造成破坏。
    
    具体来说,
    is需要知道Memory<T>
      是否是对
    • 固定内存对象
      的引用——或者是否不是。这是一个简单的 2 状态值,可以用内存中的单个位表示,而 
      _object
      (C# 中的 
      System.Boolean)类型使用整个 8 位(以及编组到 Win32 时的 四个字节
      bool
      值)。
      因此 BOOL 需要一个 1 位字段,并且它对 
      Memory<T>
    • _index
    • 使用 32 位整数,并且这两个字段将只保存 31 位值 - 所以它
      偷偷地占用了
      _length
      的 MSB 用于存储“是否固定内存”状态。
      在 .NET Core 和 .NET 5+ 的 _length 的最新版本中,他们交换了字段,现在使用 
      System.Memory
      字段来存储标志,而不是
        _index
      • 字段。
        
        
        
        
        
        
      这将在同期源代码中揭示(git commit
    • _length
    用于构建这个确切版本的
  • 32b491939fbd125f304031c35038b1e14b4e3958
-
该提交已从 .NET 的官方存储库中消失了

)。

System.Memory.dll

...但对于 .NET Core / .NET 5+:

引用来源

_index 的最高位用于辨别 [assembly: AssemblyInformationalVersion("4.6.31308.01 @BuiltBy: cloudtest-841353dfc000000 @Branch: release/2.1-MSRC @SrcCode: https://github.com/dotnet/corefx/tree/32b491939fbd125f304031c35038b1e14b4e3958")] 是否是预固定数组。

因此,为了让

_object

 属性返回有意义的值,它不能简单地按原样返回 
Length

字段;它需要首先消除标志位,否则其消费者可能会认为他们手上有 4GB 分配。


© www.soinside.com 2019 - 2024. All rights reserved.