Самый быстрый способ сравнить две строки одинаковой длины

#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 это хороший подход.