zoukankan      html  css  js  c++  java
  • C#中各种数组的性能比较

    在C#中提供了一维数组,多维数组,和交错数组(也叫齿状数组Jagged Array),由于C#本身并不直接支持非0基(0基的意思是数组的最小索引是0)的数组(虽然可以通过Array.CreateInstance()方法在C#中创建非0基数组),而且CLS(通用语言规范)也并不支持非0基数组,所以这篇文章中不讨论非0基数组。
    1,一维0基数组:
       一般情况下,建议大家最好使用一维0基数组,在C#直接支持的数组中,这种类型的数组性能最好,因为在IL中直接提供了特殊的指令来操作一维0基数组,大家看看如下的代码:
       int[] arr = new int[5];
       int i = arr[3];
       这两行代码生成的IL是这样的:
      .entrypoint
      // 代码大小       13 (0xd)
      .maxstack  2
      .locals init ([0] int32[] arr,
               [1] int32 i)
      IL_0000:  nop
      IL_0001:  ldc.i4.5
      IL_0002:  newarr     [mscorlib]System.Int32
      IL_0007:  stloc.0
      IL_0008:  ldloc.0
      IL_0009:  ldc.i4.3
      IL_000a:  ldelem.i4
      IL_000b:  stloc.1
      IL_000c:  ret
    大家可以看到IL提供了newarr指令来新建一个数组,ldelem.i4指令来获取Int32类型的数组元素,此外IL还6提供了其他的指令来操作一维0基数组:
    ldelema   :读取一维0基数组中一个元素的地址

    ldlen     :读取一维0基数组中的元素个数

    stelem    :为数组中的一个元素赋值

    ldelem.ref:则用于操作所有包含引用类型对象的数组

    2,交错数组
       交错数组实际上就是数组的数组,也就是说交错数组中的每个元素本身又是一个数组,每个嵌套数组并不要求长度一致,大家看如下代码:

                int[][] arr = new int[5][];
                arr[0] = new int[3];
                arr[1] = new int[4];
                arr[2] = new int[5];
                arr[3] = new int[6];
                arr[4] = new int[7];

                int i=arr[3][4];

    生成的IL代码如下:
      .entrypoint
      // 代码大小       60 (0x3c)
      .maxstack  3
      .locals init ([0] int32[][] arr,
               [1] int32 i)
      IL_0000:  nop
      IL_0001:  ldc.i4.5
      IL_0002:  newarr     int32[]
      IL_0007:  stloc.0
      IL_0008:  ldloc.0
      IL_0009:  ldc.i4.0
      IL_000a:  ldc.i4.3
      IL_000b:  newarr     [mscorlib]System.Int32
      IL_0010:  stelem.ref
      IL_0011:  ldloc.0
      IL_0012:  ldc.i4.1
      IL_0013:  ldc.i4.4
      IL_0014:  newarr     [mscorlib]System.Int32
      IL_0019:  stelem.ref
      IL_001a:  ldloc.0
      IL_001b:  ldc.i4.2
      IL_001c:  ldc.i4.5
      IL_001d:  newarr     [mscorlib]System.Int32
      IL_0022:  stelem.ref
      IL_0023:  ldloc.0
      IL_0024:  ldc.i4.3
      IL_0025:  ldc.i4.6
      IL_0026:  newarr     [mscorlib]System.Int32
      IL_002b:  stelem.ref
      IL_002c:  ldloc.0
      IL_002d:  ldc.i4.4
      IL_002e:  ldc.i4.7
      IL_002f:  newarr     [mscorlib]System.Int32
      IL_0034:  stelem.ref
      IL_0035:  ldloc.0
      IL_0036:  ldc.i4.3
      IL_0037:  ldelem.ref
      IL_0038:  ldc.i4.4
      IL_0039:  ldelem.i4
      IL_003a:  stloc.1
      IL_003b:  ret

    代码比较长,前面基本都是初始化的代码,大家不用太关心,但是大家明显能看到一维0基的交错数组同样也可以利用IL为一维0基数组提供的特殊指令,所以性能和一维0基数组相同,唯一的不同是多了一次嵌套数组的访问!
       
    3,多维数组:
       多维数组一般大家可能直观上的认为多维数组的性能也应该不错,因为而多维数组当中,由于用于存储元素的内存空间是连续的,而且数组的每一维元素个数固定,所以可以轻易的根据元素各维的索引值计算出元素在数组内存中偏移量,比如,一个多维数组arr[6,7],元素arr[2,4]的偏移量是2*7+4,事实证明这种直观看法并不正确,我们看如下代码:

    int[,] arr = new int[5,6];
    int i = arr[3, 4];

    生成的IL代码如下:
      .entrypoint
      // 代码大小       19 (0x13)
      .maxstack  3
      .locals init ([0] int32[0...,0...] arr,
               [1] int32 i)
      IL_0000:  nop
      IL_0001:  ldc.i4.5
      IL_0002:  ldc.i4.6
      IL_0003:  newobj     instance void int32[0...,0...]::.ctor(int32,
                                                                 int32)
      IL_0008:  stloc.0
      IL_0009:  ldloc.0
      IL_000a:  ldc.i4.3
      IL_000b:  ldc.i4.4
      IL_000c:  call       instance int32 int32[0...,0...]::Get(int32,
                                                                int32)
      IL_0011:  stloc.1
      IL_0012:  ret

    大家都知道,数组是继承于Array的引用类型,这里int32[0...,0...]类型就是CLR为多维数组构造的一个类型,Get(int32,int32)方法是CLR为这个类型构造的一个方法,类似的方法还有:

    int Get(int d1, int d2);   //获取特定元素的值

    void Set(int d1, int d2, int v); //设置特定元素的值

    int* Address(int d1, int d2);    //获取特定元素的地址

    函数调用本身是比较耗时的,因为它包含了参数的压栈出栈,以及程序控制流的转移等,显然,多维数组的这种通过函数调用来访问元素的方式没有一维0基的交错数组直接使用IL指令的方式快!



      
  • 相关阅读:
    Android 主题theme说明 摘记
    Android开发 去掉标题栏方法 摘记
    安卓项目五子棋代码详解(二)
    关于 ake sure class name exists, is public, and has an empty constructor that is public
    百度地图3.0实现图文并茂的覆盖物
    android onSaveInstanceState()及其配对方法。
    关于集成科大讯飞语音识别的 一个问题总结
    android 关于 webview 控制其它view的显示 以及更改view数据失败的问题总结
    C# 解析 json Newtonsoft果然强大,代码写的真好
    c#数据类型 与sql的对应关系 以及 取值范围
  • 原文地址:https://www.cnblogs.com/xuefeng1982/p/1678152.html
Copyright © 2011-2022 走看看