Miroslav Zadravec
Miroslav Zadravec

Reputation: 3730

Structure constructor in .net: any overhead?

About using structure constructors; are those two code blocks equal in performance?

With constructor:

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

No constructor:

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

First one is shorter, especially if constructor would have more arguments, but is it wise to use it in loops (let say game loop fired 60 times per second)? Or are those two compiled to the same machine code?

Upvotes: 1

Views: 113

Answers (2)

Hans Passant
Hans Passant

Reputation: 942000

Timing this code isn't really possible. You'll only get realistic timing results if you run the Release version of the code. Which also kicks in the JIT optimizer. And it is smart enough to see that "pt" isn't actually used anywhere, it removes all code that assigns it. You'll end up with the exact same time and still not know anything.

To force the JIT optimizer to actually emit the assignment code, you have to do something with "pt". Like:

Console.WriteLine(pt)

But now you'll be timing how long Console.WriteLine() takes instead of finding out anything about the efficiency of the assignment. What's worthy in this case however is to look at the machine code that's generated. Here's an annotated version of what my x86 JIT compiler generated in the Release build with the optimizer enabled:

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

The [elided] section is the Console.WriteLine() call. Look closely at the machine code instructions:

It is the exact same code.

The JIT compiler is cool that way. If you ask it to do the same job it generates the same code. The common advice is to code for clarity instead of efficiency. While such a statement isn't often verified, it is often accurate.

Upvotes: 6

Tim Robinson
Tim Robinson

Reputation: 54764

I'd hope these give the same machine code, assuming Point is a .NET structure (a value type, as opposed to a reference type), and assuming the Point constructor does nothing but assign to the X and Y fields. I'd expect the JIT to inline the call Point constructor.

There is, however, a difference in the IL, because the compiler doesn't inline the constructor. As you'd expect, the first piece of code makes 1000 calls to the constructor, whereas the second makes 1000 pairs of field store operations.

As always with "which is faster?" questions, write them both and time them. Stopwatch is useful for this.

Upvotes: 1

Related Questions