Конструктор структуры в .net: какие-либо накладные расходы? - PullRequest
1 голос
/ 28 июля 2010

Об использовании конструкторов структуры;равны ли эти два блока кода по производительности?

С конструктором:

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

Первый короче, особенно если у конструктора будет больше аргументов, но разумно ли его использоватьв циклах (скажем, игровой цикл запускается 60 раз в секунду)?Или эти два скомпилированы в один и тот же машинный код?

Ответы [ 2 ]

6 голосов
/ 28 июля 2010

Синхронизация этого кода на самом деле не возможна.Вы получите реалистичные результаты синхронизации только в том случае, если вы запустите версию кода.Который также пинает в оптимизаторе JIT.И он достаточно умен, чтобы видеть, что «pt» фактически нигде не используется, он удаляет весь код, который его присваивает .Вы получите то же самое время и все еще ничего не знаете.

Чтобы заставить оптимизатор JIT фактически выдавать код назначения, вы должны сделать что-то с "pt".Например:

Console.WriteLine(pt)

Но теперь вы будете определять, сколько времени займет Console.WriteLine () вместо того, чтобы что-то выяснять об эффективности назначения.Однако в этом случае стоит взглянуть на сгенерированный машинный код.Вот аннотированная версия того, что мой JIT-компилятор x86 сгенерировал в сборке выпуска с включенным оптимизатором:

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 в этом отношении крут.Если вы попросите его выполнить ту же работу, он сгенерирует тот же код.Общий совет состоит в том, чтобы кодировать для ясности вместо эффективности.Хотя такое утверждение не часто подтверждается, оно часто является точным.

1 голос
/ 28 июля 2010

Я надеюсь, что они дают тот же машинный код, предполагая, что Point является структурой .NET (тип значения, а не ссылочный тип), и предполагая, что конструктор Point ничего не делает, кроме как присваивает X и Y поля. Я ожидаю, что JIT встроит конструктор вызова Point.

Однако существует разница в IL, потому что компилятор не встроен в конструктор. Как и следовало ожидать, первый фрагмент кода делает 1000 обращений к конструктору, а второй - 1000 пар операций хранения полей.

Как всегда с "что быстрее?" вопросы, напишите их и время их. Stopwatch полезен для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...