Что было бы правильнее и быстрее в C ++ 11: switch-case или if (.. || .. || ..)?

c++ c++11 optimization

76 просмотра

1 ответ

Я пытаюсь построить простой лексический анализатор - лексер. Часть, над которой я сейчас работаю, это токенизатор. Я пишу функцию, которая определяет разделители (пробелы, табуляции, новые строки (CR, LF)) во входной последовательности. Итак, вопрос в том, какой код является более правильным:

Код с оператором switch-case:

bool isWhitespace(wchar_t &symbol) {

    switch (symbol) {

        case L' ':
        case L'\t':
        case L'\r':
        case L'\n':
            return true;
        default:
            return false;

    }

}

Или код с оператором if (.. || .. || ..):

bool isWhitespace(wchar_t &symbol) {

    if (symbol == L' ' ||
        symbol == L'\t' ||
        symbol == L'\r' ||
        symbol == L'\n') {

        return true;

    }

    return false;

}

И какой из них будет быстрее?


UPD

Что ж, результат теста, сгенерированного ассамблером, и тесты скорости:

Для switch-case:

__Z12isWhitespaceRw:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    movzwl  (%eax), %eax
    movzwl  %ax, %eax
    cmpl    $13, %eax
    je  L18
    cmpl    $13, %eax
    jg  L19
    subl    $9, %eax
    cmpl    $1, %eax
    ja  L17
    jmp L18
L19:
    cmpl    $32, %eax
    jne L17
L18:
    movl    $1, %eax
    jmp L20
L17:
    movl    $0, %eax
L20:
    popl    %ebp
    ret

И для if:

__Z12isWhitespaceRw:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    movzwl  (%eax), %eax
    cmpw    $32, %ax
    je  L22
    movl    8(%ebp), %eax
    movzwl  (%eax), %eax
    cmpw    $9, %ax
    je  L22
    movl    8(%ebp), %eax
    movzwl  (%eax), %eax
    cmpw    $13, %ax
    je  L22
    movl    8(%ebp), %eax
    movzwl  (%eax), %eax
    cmpw    $10, %ax
    jne L23
L22:
    movl    $1, %eax
    jmp L24
L23:
    movl    $0, %eax
L24:
    popl    %ebp
    ret

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

И измерения скорости:

1

Переключение регистра: %time = 7.7,self = 0.01

Если: %time = 46.2,self = 0.06

2

Переключение регистра: %time = 34.6,self = 0.03

Если: %time = 34.6,self = 0.03


UPD # 2

Да, Юникод. Разве это не так очевидно, если смотреть на код ?!

Автор: PRIGORYAN Источник Размещён: 08.11.2019 11:16

Ответы (1)


2 плюса

Решение

Оба варианта верны, но версия switch / case выдаст предупреждения с некоторыми компиляторами.

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

Вторая версия проясняет происходящее. Это не типичный вариант использования переключателя / случая, но это только мое мнение.

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

Автор: Frank Puffer Размещён: 20.08.2016 12:09
Вопросы из категории :
32x32