#c #string #performance #compare
#c #строка #Производительность #Сравнить
Вопрос:
Строки имеют фиксированную длину 8, содержат буквенно-цифровые символы и дополняются пробелами справа.
То есть,
"STRING1 "
"STR2 "
"S "
и т.д..
Я подумал, memcmp
может быть, здесь самый быстрый?
Комментарии:
1. Профиль profile profile … и если сравнение строк не является узким местом в вашем приложении (т. Е. Если вы не сравниваете тысячи строк в замкнутом цикле), не стоит бесцельно чрезмерно оптимизировать.
2.
std::pair<const char*, const char*> p = std::mismatch(str1, str1 8, str2); if (p.first == str1 8) { ... }
. Для символа * библиотека c должна вызвать memcmp.3. Для предложения @Kerrek есть научная причина: закон Амдала . Короче говоря: если вам нужно оптимизировать, сначала найдите наиболее частый случай, а затем оптимизируйте его
Ответ №1:
Если вы убедитесь, что строки выровнены по 8-байтовой границе с помощью специфичных для компилятора атрибутов, вы можете сделать:
uint64_t a = *((uint64_t *) "STRING1 ");
uint64_t b = *((uint64_t *) "STR2 ");
Тогда a == b
должна быть выдана одна 64-разрядная инструкция.
Или, если это просто постоянные неизменяемые строки (хранящиеся в области процесса, доступной только для чтения), вы можете продолжить сравнение const char *
самих указателей. Это все еще надежный тест, поскольку строковый литерал, который дважды появляется в текущей единице перевода, должен ссылаться на одну и ту же память:
/* fails because the two strings are stored at different locations */
"STRING1 " == "STR2 "
/* should succeed, even the silliest compiler should merge both literals */
"STRING1 " == "STRING1 "
Комментарии:
1. Может возникнуть проблема с порядком окончания, если вы сохраните эти значения по сети, а затем загрузите их на другую платформу. Также существует вероятность того, что строка не будет выровнена должным образом для доступа — многие платформы не захотят обращаться к uint64_t, кроме как выровненных по 8-байтовой границе, но для массивов символов такого ограничения нет. 1, по крайней мере, за основу хорошей идеи — это должно быть достаточно легко для решения любых проблем.
2. Я не думаю, что это такая уж блестящая идея. На приличной платформе
memcmp
с постоянным размером в качестве параметра должно получиться что-то похожее без запутывания кода для сомнительной оптимизации.3. @JensGustedt: если вы считаете это запутыванием, то не смотрите на
ngx_strXXcmp
макросы здесь 🙂4. Недостатком является то, что это технически неопределенное поведение… если вы не найдете расширение компилятора, которое гарантирует, что это сработает.
5. @Steve314: каламбур через объединения разрешен в ISO-C99 — сноска, в которой указано, что это явно было добавлено в TC3; если вам не нравится ‘illegal’ как синоним ‘вызывает неопределенное поведение’, используйте ‘non-portable’, ‘код, который сломается, если вы неправильно посмотрите на флаги вашего компилятора’ или ‘код, который может заставить демонов вылететь из вашего носа при подтверждении реализаций’
Ответ №2:
Если строки имеют фиксированную равную длину, то memcmp
это хороший подход.