代码之家  ›  专栏  ›  技术社区  ›  Miroslav Zadravec

net中的结构构造函数:有开销吗?

  •  1
  • Miroslav Zadravec  · 技术社区  · 14 年前

    Dim pt As Point
    For i As Integer = 1 To 1000
        pt = New Point(i, i)
    Next
    

    Dim pt As Point
    For i As Integer = 1 To 1000
        pt.X = i
        pt.Y = i
    Next
    

    2 回复  |  直到 14 年前
        1
  •  6
  •   Hans Passant    14 年前

    给这个代码计时是不可能的。只有运行代码的发布版本,才能获得实际的计时结果。它还启动了JIT优化器。它很聪明地发现“pt”实际上并没有在任何地方使用, 它删除所有分配它的代码

    要强制JIT优化器实际发出分配代码,您必须使用“pt”进行一些操作。比如:

    Console.WriteLine(pt)
    

    00000008  xor         eax,eax                               ; New Point
    0000000a  mov         dword ptr [ebp-10h],eax               ; pt.X = 0
    0000000d  mov         dword ptr [ebp-0Ch],eax               ; pt.Y = 0
    [first fragment]
    00000010  mov         esi,1                                 ; i = 1
                pt = New Point(i, i)
    00000015  mov         dword ptr [ebp-10h],esi               ; pt.X = i
    00000018  mov         dword ptr [ebp-0Ch],esi               ; pt.Y = i
    [elided]
    00000036  add         esi,1                                 ; i = i + 1
    00000039  jo          0000007D                              ; overflow check
    0000003b  cmp         esi,3E8h                              ; i <= 1000?
    00000041  jle         00000015                              ; Yes: loop
    [2nd fragment]
    00000043  mov         esi,1                                 ; i = 1
                pt.X = i
    00000048  mov         dword ptr [ebp-10h],esi               ; pt.X = i
                pt.Y = i
    0000004b  mov         dword ptr [ebp-0Ch],esi               ; pt.Y = i
    [elided]
    00000069  add         esi,1                                 ; i = i + 1
    0000006c  jo          0000007D                              ; overflow check
    0000006e  cmp         esi,3E8h                              ; i <= 1000?
    00000074  jle         00000048                              : Yes: loop
    

    [elided]部分是Console.WriteLine()调用。仔细查看机器代码说明:

    这是完全相同的代码

    JIT编译器就是这样。如果你要求它做同样的工作,它会生成同样的代码。通常的建议是为了清晰而不是效率而编码。虽然这样的说法不常被证实,但往往是准确的。

        2
  •  1
  •   Tim Robinson    14 年前

    我希望它们能给出相同的机器代码,假设 Point 是.NET结构(值类型,而不是引用类型),并假定 X Y 领域。我希望JIT能把这个调用内联起来 建造师。

    但是,IL中有一个区别,因为编译器没有内联构造函数。如您所料,第一段代码对构造函数进行1000次调用,而第二段代码进行1000对字段存储操作。

    Stopwatch 是有用的。