Хит производительности двойной разыменования ссылочных типов в C # - PullRequest
0 голосов
/ 09 декабря 2011

Недавно я начал работать над проектом, в котором многие ссылочные параметры передаются по ссылке. Я просмотрел большую часть кода, и большинство этих методов могли потерять параметр ref. Несмотря на то, что код работает нормально, мне было интересно, какой может быть снижение производительности, если дважды разыменовывать каждый аргумент, а не просто передавать ссылку по значению.

Например, этот код:

public void EmptyList(ref List<string> test)
{
    test.Clear();
}

VS это:

public void EmptyList(List<string> test)
{
    test.Clear();
}

EDIT

Прочитав, что сказал Николас Кэри, я попробовал то же самое с кодом выше. Это была полученная сборка:

            EmptyList(ref List<string> test)
00000028  mov         eax,dword ptr [ebp-40h] 
0000002b  mov         ecx,dword ptr [eax] 
0000002d  cmp         dword ptr [ecx],ecx 
0000002f  call        719210C4


            EmptyList(List<string> test)
00000028  mov         ecx,dword ptr [ebp-40h] 
0000002b  cmp         dword ptr [ecx],ecx 
0000002d  call        71920FD4 

Ответы [ 2 ]

4 голосов
/ 09 декабря 2011

Разница между вызовом по явной ссылке и вызовом по неявной ссылке - это разница между инструкцией lea (Load Effective Address) и mov ('Move').

AFAIK на любомВ современном процессоре обе эти инструкции в используемой форме выполняются за один такт, поэтому разница довольно спорная.

Вот код, сгенерированный (режим отладки) для вызова по [явной] ссылке:

            FooBar( ref o ) ;
00000035  lea         ecx,[ebp-40h] 
00000038  call        FFD0B008 
0000003d  nop 

А вот код, сгенерированный (режим отладки) для вызова по [неявной] ссылке:

            FooBar( o ) ;
0000003a  mov         ecx,dword ptr [ebp-40h] 
0000003d  call        FFD3B008 
00000042  nop 

Код, сгенерированный для вызываемого метода / функции, идентиченcase.

Вот пример кода, который я использовал..

3 голосов
/ 09 декабря 2011

Разница в производительности, вероятно, будет совершенно незамеченной, если она вообще существует. Я бы лично решил, передавать ли «эталонные параметры» по ссылке или по значению по функциональным требованиям , а не по различиям в производительности.

Передача ссылочного типа с использованием ref имеет сильное значение для вызывающей стороны. Предполагается, что ваша ссылка может измениться. Это имеет явное значение для использования вашего API и убедительно показывает, что вы можете изменять значения. Если это не так, передайте ссылку по значению, чтобы избежать путаницы, так как это приведет к более понятному и понятному коду.

...