Могу ли я рассчитывать на мой компилятор для оптимизации 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)
{
}
}
Это чистая победа в удобочитаемости, но я понятия не имею о стоимости производительности.
В качестве альтернативы, если вы должны отправить самостоятельно, я обнаружил, что использование подхода, подобранного как состояние (со стеклом), намного лучше читаемо и может также выигрывать по производительности (вместо того, чтобы иметь большое количество тегов для включения у вас есть только те теги, которые могут быть выполнены прямо сейчас).