могу ли я рассчитывать на мой компилятор для оптимизации strlen на const char *? - PullRequest
14 голосов
/ 24 апреля 2011

В моем обратном вызове синтаксического анализа SAX 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 и оптимизировать сравнения строк.

Ответы [ 4 ]

10 голосов
/ 24 апреля 2011

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

static const char* kFoo = "Bar";

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

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

static const char *const kFoo = "Bar";

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

static const char kFoo[] = "Bar";

или даже:

#define kFoo "Bar"
10 голосов
/ 24 апреля 2011

Если под "LLVM" вы подразумеваете лязг, то да, вы можете рассчитывать на 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 голосов
/ 24 апреля 2011

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

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

#define kFoo "..."

    ... strcmp(... sizeof(kFoo))
0 голосов
/ 26 апреля 2011

Дополнительный вопрос:

Вы проверяли следующее?

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

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

  }


}

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

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

...