Замедляет ли метод вызова производительность? - PullRequest
6 голосов
/ 07 декабря 2011

Например:
Код 1:

void Main()
{
    Console.WriteLine("Some texts");
}

Код 2:

void Main()
{
    Foo();
}

void Foo()
{
    Console.WriteLine("Some texts");
}

Работает ли код 2 медленнее, чем код 1?Хотя, когда мы собираем релиз, JIT встроит код 2, поэтому код 2 будет работать так же быстро, как и код 1. Но когда я тестирую их с LinqPad , я получаю результат IL:

Код 1:

IL_0000:  ldstr       "Some texts"
IL_0005:  call        System.Console.WriteLine

Код 2:

IL_0000:  ldarg.0     
IL_0001:  call        UserQuery.Foo

Foo:
IL_0000:  ldstr       "Some texts"
IL_0005:  call        System.Console.WriteLine
IL_000A:  ret      

Как мы видим, результат IL в коде 2 имеет несколько дополнительных шагов для вызова Foo (), доказывает ли это, что код 2работать медленнее, чем код 1?

Ответы [ 6 ]

10 голосов
/ 07 декабря 2011

Прежде всего, вы смотрите на IL, а не на код сборки JITted.То, что вы показали, ничего не доказывает.Вам нужно посмотреть на вывод JITted, чтобы увидеть, вставил ли JITter код или нет.Обратите внимание, что JITter отличается от платформы к платформе (например, x86 против x64) и от версии Framework до версии Framework.

Во-вторых, конечно, поскольку написанная версия два будет работать медленнее, чем версия первая.Когда я говорю «как написано», я имею в виду, что это предполагает, что JITter не встроил вызов во второй версии.Дополнительный вызов добавляет несколько машинных инструкций, которые, конечно, требуют несколько дополнительных циклов для выполнения (опять же, не забудьте, что я сказал «как написано!»).Однако разница в производительности чрезвычайно велика и вряд ли будет значимой.Вы должны были бы делать это в самом узком цикле триллионов и триллионов итераций, чтобы когда-либо видеть существенную разницу в производительности.

2 голосов
/ 07 декабря 2011

В этом случае, с реализацией, как это было в прошлый раз, когда я читал о таких вещах, да, это будет встроено.

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

На практике:

Если вы подозреваете, что рабочая точка производительности может выиграть от ручного встраивания, попробуйте ее и выполните профилирование еще раз. Или, по крайней мере, посмотрите на объединенный код для этой конкретной части.

В теории:

Тем не менее, мне нравится знать, что маленькие методы встроены, все же.

2 голосов
/ 07 декабря 2011

Да, вызовы методов немного замедляют выполнение кода, если они не встроены c # -компилятором или jit-компилятором.Однако, если ваш код не выполняется в цикле и выполняется миллион раз или около того, вы должны сосредоточиться на создании чистого, понятного и обслуживаемого кода.Когда я начинал с программирования, время выполнения для отдельных операторов измерялось в миллисекундах или секундах.Сегодня они измеряются в наносекундах.Время обычно тратится впустую на операции ввода / вывода.Плохие алгоритмы также могут быть обвинены несколько раз.Если ваш дизайн четко структурирован, гораздо проще заменить плохо работающую часть кода на более качественную, по сравнению с кодом, оптимизированным по времени с самого начала и поэтому, вероятно, плохо структурированным.испытал это недавно.Мне пришлось создать сложную графику в Visio в программе ac #.Оказалось, что Visio-автоматизация была очень медленной.Потребовалось несколько минут, чтобы создать графику.К счастью, я поместил все графические элементы в компонент, который отображал графические команды через нейтральный интерфейс продукта.Т.е. интерфейс не содержал никаких специфических вещей для Visio.Было очень легко заменить мой компонент Visio новым SVG-компонентом, который выполнил ту же задачу менее чем за секунду.Кроме того, абсолютно не нужно было вносить никаких изменений в мои алгоритмы или в любую другую часть моей программы.

Конечно, мой компонент графической оболочки добавляет больше вызовов методов.Кроме того, доступ к нему осуществляется через интерфейс, который еще больше замедляет процесс.Однако, в конце концов, именно этот интерфейс и эти дополнительные вызовы методов позволили мне реализовать гораздо более быстрое решение.Помните: минуты против одной секунды!

1 голос
/ 07 декабря 2011

Компилятор C # не делает вставку, и это то, что вы видите в коде IL. Встраивание - это работа оптимизатора JIT, которая выполняет ее во время выполнения (если она решает, что включение функции делает программу более эффективной).

1 голос
/ 07 декабря 2011

Это так тривиально (читай: может быть), вам не нужно беспокоиться об этом.

0 голосов
/ 07 декабря 2011

Компилятор создает свою собственную интерпретацию кода (ассемблерного кода), поэтому примеры кода будут обрабатываться одинаково для CPU.(в режиме разблокировки)

...