Pull to refresh

Comments 14

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

У вас не совсем одинаковые методы. В случае с ветвлением у вас попугай — это по сути дефолтная ветка (вы не делаете проверку на попугая), а вот в switch блоке делается дополнительная проверка и есть дополнительный дефолтный кейс с исключением. Ожидаемо switch медленнее.
Еще было бы интересно померить switch-expression. Если сделать попугая дефолтной веткой везде, switch генерируют похожий код (хотя expression имеет дополнительную локальную переменную), см. SharpLab.


UPD: В примере я явно указал базовый тип перечисления как byte, что привело к возникновению разных неоптимальных asm-инструкций (что странно). Оставив тип перечисления по умолчанию (int32), asm-код для обоих switch оказался идентичным (как и ожидалось). Ссылка заменена.

Могу сразу сказать, что если у вас где-то встретилось


public static Animal CreateAnimalByTernaryOperator(bool isCat)
{
    return isCat ? (Animal)new Cat() : new Dog();
}

То где-то вы свернули не туда. В очень редких случаях такое бывает нужно, но тогда нужно заводить нормальный энум enum AnimalType { Cat, Dog } с самого начала, а не ждать пока появятся попугаи.


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

Ну как — наверняка есть наиболее вероятный исход, который можно поставить по более быстрой ветке, но надо учитывать, что в тернарном операторе это false ветка, а в if-else, наоборот :)

Какая-то уж совсем преждевременная оптимизация получается.
На фоне выделений памяти и прочего.

На то и смайлик. Но чем чёрт не шутит ;)

Во-первых, есть бранч предиктор, который снизит стоимость джампа почти до нуля (если мы предполагаем. что true/false приходит достаточно стабильно, если нет, то какая ветка дефолтная уже не важно).
Во-вторых если мне будет жалко одного такта на джамп то я скорее поменяю ветки if/else (есть автоматический рефакторинг в студии и райдере), чем буду тернарник делать. Тем более, что он не умеет во что-то чуть более сложное чем 2 экспрешна.
Ну а в-третьих в языке с ГЦ и миллионом ненужных аллокаций это всё курам на смех. LINQ в 10 раз медленнее циклов, но все пишут на них (кроме избранных, которые и верстку рендерят на стрингбилдерах).


Есть некоторая грань, до которой перфоманс можно получать бесплатно, просто грамотно продумывая архитектуру, а за ней начинается безумие, когда лучше взять какой нибудь раст и иметь 1500% буст перфоманса без пляски над тем что джит выплюнул. Тем более, что это нигде не документировано, так что вчера там был brtrue, а завтра — brfalse. Да еще и tiered JIT есть, который может увидеть паттерн и спокойно перекомпилировать, поменяв ветки местами.

не уверен насчет шарпа. Но в Си switch на большом кол-ве условий будет быстрей. Так как это по сути превращается в таблицу безусловных переходов
Что вы такое пишете что дошли до измерения производительности основных конструкций языка? По моему это бесполезные измерения… Premature optimization во всей красе…
Лично у меня был исключительно академический интерес, который возник с вопроса: «Равнозначен ли будет код через ?: и if-else?» В реальных проектах, безусловно, эти оптимизации не имеют никакого значения. Как писали выше, бранч предиктор всё равно сведёт выигрыш от них до нуля.
Я думаю, что делать такой вывод будет не совсем корректно. Возможно, что BenchmarkDotNet в .NetCore делает замеры немного иначе, чем в фреймворке.

Так как IL-код для .NetCore и .NET Framework одинаковый, надо посмотреть, какие команды процессору получаются в результате JIT-компиляции. Но для этого нужно читать исходники JIT'а, что, скорее всего, не самое простое занятие.
IL-код не имеет никакого значения при замере быстродействия
Sign up to leave a comment.

Articles