• 关于 Span 的一切:探索新的 .NET 明星:5. .NET 运行时的处理


    .5. NET 运行时会怎么样?

    .NET 运行时提供的安全保证之一是确保访问数组的下标不会越界,实践中被称为边界检查,考虑如下方法:

    [MethodImpl(MethodImplOptions.NoInlining)]
    static int Return4th(int[] data) => data[3];
    

    在我撰写本文的 x64 机器上,生成的汇编代码如下所示:

    sub      rsp, 40
           cmp      dword ptr [rcx+8], 3
           jbe      SHORT G_M22714_IG04
           mov      eax, dword ptr [rcx+28]
           add      rsp, 40
           ret
    G_M22714_IG04:
           call     CORINFO_HELP_RNGCHKFAIL
           int3
    

    cmp 指令比较下标 3 与数组的长度,如果下标 3 越界,随后的 jbe 指令跳转到检查失败代码 ( 抛出异常 )。JIT 需要生成代码来确保此类访问不会导致下标越界,但是这不意味着每次独立的数组访问都需要边界检查。考入下面的 Sum 方法:

    static int Sum(int[] data)
    {
      int sum = 0;
      for (int i = 0; i < data.Length; i++) sum += data[i];
      return sum;
    }
    

    JIT 需要生成确保访问 data[i] 的代码不会下标越界,但是因为可以告诉 JIT,从循环结构 i 永远不会越界 ( 循环从头到尾遍历每个元素 ),JIT 可以优化掉对数组访问的边界检查。这样,生成的汇编代码如下所示:

    G_M33811_IG03:
           movsxd   r9, edx
           add      eax, dword ptr [rcx+4*r9+16]
           inc      edx
           cmp      r8d, edx
           jg       SHORT G_M33811_IG03
    

    cmp 指令还在循环中,但是只是简单地比较下标 i 和数组的长度 ( 它保存在 r8d 寄存器中 ),没有了其它的边界检查。

    运行时使用类似对 Span ( 包括 Span<T> 和 ReadOnlySpan<T> ) 的优化。对比上一示例的如下代码,这里仅仅变更了参数类型:

    static int Sum(Span<int> data)
    {
      int sum = 0;
      for (int i = 0; i < data.Length; i++) sum += data[i];
      return sum;
    }
    

    上述代码生成的汇编代码几乎相同。

    G_M33812_IG03:
           movsxd   r9, r8d
           add      ecx, dword ptr [rax+4*r9]
           inc      r8d
           cmp      r8d, edx
           jl       SHORT G_M33812_IG03
    

    汇编代码非常类似,因为省去了边界检查。但是因为 JIT 识别到 Span 原生的索引器,意味着 JIT 对索引器生成特定的代码,而不是转换实际代码到汇编中。

    所有这些说明了,对于运行时可以使用 Span 对数组相同类型的优化,使得 Span 成为访问数据的高效机制。更深入内容请参见:bit.ly/2zywvyI

  • 相关阅读:
    SQL Reporting Services Report Viewer Scroll Bar(RDLC)
    SQL Server日期格式转换大全
    Export GridView to Excel within an UpdatePanel
    ASP.NET CompareValidator validate Currency
    微軟 Office 2003 版本比較一覽表
    打开Safari的Javascript调试功能
    SQL SERVER 2000/2005 列转行 行转列
    [Java] 使用cookie保持Session (Axis2 和 WSIT)
    .NET通用权限系统快速开发框架
    Java进阶对象与内存控制(一)
  • 原文地址:https://www.cnblogs.com/haogj/p/16228246.html
Copyright © 2020-2023  润新知