Могу ли я рассчитывать на мой компилятор для оптимизации strlen на const char *?

В моем обработчике разбора XML xml (XCode 4, LLVM) я делаю много вызовов этот тип кода:

static const char* kFoo = "Bar";

void SaxCallBack(char* sax_string,.....)
{
     if ( strcmp(sax_string, kFoo, strlen(kFoo) ) == 0)
     {

     }


  }

Можно ли предположить, что strlen (kFoo) оптимизирован компилятором?

(Пример кода Apple был предварительно рассчитан strlen (kFoo), но я думаю, что это ошибка, подверженная большому количеству постоянных строк.)

Изменить: Мотивация для оптимизации: разбор моей SVG-карты на iPod touch 2G занимает 5 секунд (!) с использованием NSXMLParser. Итак, я хочу перейти на lib2xml и оптимизировать сравнение строк.

Ответ 1

Если "LLVM" означает "clang", то да, вы можете рассчитывать на clang -O, чтобы оптимизировать strlen. Вот как выглядит код для вашей функции:

_SaxCallBack:
Leh_func_begin1:
    pushq   %rbp
Ltmp0:
    movq    %rsp, %rbp
Ltmp1:
    leaq    L_.str1(%rip), %rsi
    movl    $3, %edx
    callq   _strncmp
    ...

Я изменил strcmp на strncmp, но третий аргумент действительно был заменен непосредственным $3.

Обратите внимание, что gcc 4.2.1-O3 не оптимизирует этот вызов strlen и что вы можете ожидать, что он будет работать в точном состоянии вашего вопроса (особенно, строка и вызов strlen должны быть в том же файле).

Ответ 2

Не пишите такие вещи, как:

static const char* kFoo = "Bar";

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

Также не пишите такие вещи, как:

static const char *const kFoo = "Bar";

Теперь ваша переменная kFoo const -qualified и немодифицируема, но если она используется в независимом от позиции коде (разделяемые библиотеки и т.д.), содержимое будет по-прежнему изменяться во время выполнения и, таким образом, оно добавит запуск и память стоимость вашей программы. Вместо этого используйте:

static const char kFoo[] = "Bar";

или даже:

#define kFoo "Bar"

Ответ 3

В общем, вы не можете рассчитывать на это. Однако вы можете использовать 'sizeof' и применить его к строковому литералу. Конечно, это означает, что вы не можете определить "kFoo" так, как он был определен.

Следующее должно работать на всех компиляторах и на всех уровнях оптимизации.

#define kFoo "..."

    ... strcmp(... sizeof(kFoo))

Ответ 4

Последующий вопрос:

Вы тестировали следующее?

static std::string const kFoo = "BAR";

void SaxCallBack(char* sax_string,.....)
{
  if ( sax_string == kFoo)
  {

  }


}

Это чистая победа в удобочитаемости, но я понятия не имею о стоимости производительности.

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