Может ли порядок регистров в операторе Switch влиять на производительность? - PullRequest
18 голосов
/ 12 мая 2010

Допустим, у меня есть оператор переключения, как показано ниже

switch(alphabet) {

    case "f":
        //do something
        break;

    case "c":
        //do something
        break;

    case "a":
        //do something
        break;

    case "e":
        //do something
        break;

}

Теперь предположим, что я знаю, что частота Alphabet e самая высокая, за которой следуют a, c и f соответственно. Итак, я просто реструктурировал порядок операторов case и сделал их следующим образом:

switch(alphabet) {

    case "e":
        //do something
        break;

    case "a":
        //do something
        break;

    case "c":
        //do something
        break;

    case "f":
        //do something
        break;
}

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

Ответы [ 4 ]

21 голосов
/ 12 мая 2010

Не так много, что вы должны быть обеспокоены. Это, конечно, не то, что можно предсказать.

При использовании строковых меток компилятор фактически использует внутреннюю хеш-таблицу, которая отображает строки в индексы в таблице переходов. Таким образом, операция на самом деле O (1) - независимо от количества меток.

Для целочисленных меток, то я считаю, что фактический генерируемый код зависит от количества меток и от того, являются ли числа последовательными (или «почти» последовательными). Если они последовательны (1, 2, 3, 4, ...), то они просто преобразуются в таблицу прыжков. Если их много, то будет использоваться таблица переходов Hashtable + (как со строками). Если есть только несколько меток, и они не являются таблицами, которые будут немедленно преобразованы в таблицу переходов, только тогда будет преобразован в серию операторов if..then..else.

В общем, однако, вы должны писать код так, чтобы вы могли читать его , а не так, чтобы компилятор мог генерировать "более быстрый" код.

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

2 голосов
/ 12 мая 2010

Это зависит от того, как компилятор реализует оператор switch.

Во-первых, вы не можете произвольно переставлять порядок; если у вас есть один блок дела в C-подобном языке (C, C ++, C #, Java, ...), и этот блок case не прервать в перерыве, вы не можете изменить порядок дел, потому что отсутствие разрыв означает, что компилятор должен реализовать переход к следующему случаю. Если мы проигнорируем эту особую ситуацию, вы можете переставить остальные случаи.

Если количество падений мало, компилятор может реализовать тесты падежей по последовательности сравнений. Если число случаев является скромным, это может построить сбалансированное бинарное дерево из кейсов. Если количество случаев большое, большинство компиляторы реализуют индексированную ветвь на значении переключателя, если оно плотный набор. Если части набора значений регистра плотны, а части нет, компилятор может разбивать дела на группы, используя двоичное дерево выбрать плотное множество и индексный переход в плотном наборе. (Фактически, компилятор может технически делать все, что передает управление соответствующий случай, но чаще всего это один из вышеперечисленных).

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

2 голосов
/ 12 мая 2010

Они имеют одинаковую производительность при относительно небольшом наборе значений. Я пытался проверить код сборки программы на C раньше, компилятор создает таблицу переходов из всех значений, которые есть в вашем операторе switch.

Но если значения падежа слишком велики, можно с уверенностью предположить, что они выродятся до if else if, поэтому размещение вашего кейса 'E' наверняка ускорит процесс.

Это также применимо в C #, C # также создает таблицу переходов для операторов switch с небольшим набором, хотя и только для смежных значений. Так что это O (1), нет многократного тестирования, даже если первые значения не совпадают.

0 голосов
/ 12 мая 2010

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

Итак, если вы внесли изменения для определения приоритетов частоты, ответ - да, это может как-то помочь с производительностью. Но я верю, что это не сильно поможет.

...