В чем разница между ldsfld и ldstr в IL? - PullRequest
8 голосов
/ 09 сентября 2010

Я прочитал некоторую статью о String.Empty vs "", и я также делаю тестирование самостоятельно. Разное между ними ниже.

String.Empty

L_0001: ldsfld string [mscorlib]System.String::Empty

""

L_0001: ldstr ""

После того, как я поговорю с моими друзьями, они утверждают, что String.Empty быстрее, чем "", потому что под капотом (на уровне сборки) ldstr делает больше на 1 круг, чем ldsfld. (Я не могу вспомнить шаги, которые делают их разными)

Я хочу знать, как я могу проверить этот аспект производительности.

Ответы [ 3 ]

13 голосов
/ 09 сентября 2010

Операция ldsfld помещает значение статического поля в стек оценки, тогда как ldstr передает ссылку на литерал строки метаданных.

Разница в производительности (если есть) будет минимальной. Более новые версии компилятора фактически заменяют "" на String.Empty.

Вы также должны учитывать удобочитаемость и удобство сопровождения кода. Используя String.Empty, становится понятнее, что вы имеете в виду пустую строку, а не просто забыли набрать что-то в строковом литерале.

Edit:

Я посмотрел на созданный нативный код.

C # 3, режим выпуска, x86:

        string a = String.Empty;
0000002a  mov         eax,dword ptr ds:[0356102Ch]
0000002f  mov         dword ptr [ebp-8],eax
        string b = "";
00000032  mov         eax,dword ptr ds:[0356202Ch]
00000038  mov         dword ptr [ebp-0Ch],eax

C # 3, режим разблокировки, x64:

        string a = String.Empty;
0000003b  mov         rax,12711050h 
00000045  mov         rax,qword ptr [rax] 
00000048  mov         qword ptr [rsp+28h],rax 
        string b = "";
0000004d  mov         rax,12713048h 
00000057  mov         rax,qword ptr [rax] 
0000005a  mov         qword ptr [rsp+30h],rax 

Итак, в итоге код идентичен.

7 голосов
/ 01 апреля 2013

От .NET 4.5 разница в данном случае : абсолютно ничего. Похоже, что JIT теперь обнаруживает этот ldsfld и вставляет пустую строку напрямую.

Вы можете сказать это, потому что в <4.5 вы можете изменить значение string.Empty с помощью отражения, и это повлияет на код с помощью string.Empty. Противно, но возможно. С 4.5 это больше не работает. Если вы можете проверить с помощью отражения, вы получите взломанную версию, но код с использованием строки. Пустой через ldsfld получает правильную пустую строку вместо взломанной версии. </p>

7 голосов
/ 09 сентября 2010

ldstr - это IL для загрузки определенного строкового токена из метаданных.

ldsfld - это IL для загрузки указанного поля - в данном случае string.Empty.

Другими словами, это совершенно разные операции, которые в этом случае имеют одинаковый результат.Как они реализованы на уровне сборки?Ну, это вполне может зависеть от версии CLR, которую вы используете.Спросите своих друзей, о какой версии они говорят ... настольный компьютер (32 или 64 бит? 1, 2, 2SP1, 2SP2, 4?), Compact Framework (опять же, какая версия?), Silverlight (какая операционная система, какая версия?) Они использовали cordbg в коде, который вы на самом деле обсуждали, или они сделали это в некотором примере кода, который, возможно, не был оптимизирован таким же образом?

Я бы (и имел)утверждал, что вы должны использовать то, что вы найдете более читабельным.Лично я предпочитаю "", но другие предпочитают string.Empty.Все в порядке.Чтобы спорить друг с другом по соображениям производительности, требуется свидетельство , хотя ... и в идеале, свидетельство, основанное на коде, который вы на самом деле пишете, а не микропроцессор.

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

...