Подтвердить что ты не робот

Может ли порядок действий в инструкции Switch изменять производительность?

Скажем, у меня есть оператор switch, как показано ниже

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 много раз, это будет существенное улучшение? Или, если нет, то каким образом я могу использовать свои частотные знания для повышения производительности?

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

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