Недавно было выпущено предложение по ядру Linux, в который предлагается включить набор патчей с оптимизированная реализация функции memchr() используется для поиска символа в массиве.
Функция memchr() сканирует первые n байтов области памяти, на которую указывает s, в поисках первого экземпляра c. И c, и байты в области памяти, на которую указывает s, интерпретируются как символы без знака.
предложение обещает быть быстрее найти символ в блоке памяти. В тестах разработчиков новая реализация может работать почти в четыре раза быстрее при больших объемах поиска.
В отличие от предыдущей версии, в которой использовалось побайтовое сравнение, предлагаемая реализация создана с учетом полного использования 64-битных и 32-битных регистров ЦП. Вместо байтов сравнение выполняется с использованием машинных слов, что позволяет одновременно сравнивать не менее 4 байтов.
Эта серия патчей оптимизировала "memchr()" и добавила макрос для
"memchr_inv()", чтобы обе функции могли использовать его для создания битовой маски.Первоначальная реализация "memchr()" основана на сравнении байтов,
который не полностью использует 64- или 32-битный регистр ЦП. Мы реализуем
сравнение по словам так, чтобы хотя бы 4 байта можно было сравнить с одним и тем же
погода. Оптимизированная функция memchr() работает почти в 4 раза быстрее исходной.
для длинных цепочек. В ядре Linux мы обнаруживаем, что длина строки
который ищется с помощью «memchr()», составляет до 512 байт в drivers/misc/lkdtm/heap.c.
При поиске в больших строках новая версия оказалась примерно в 4 раза быстрее старой (например, для строк из 1000 символов). Для небольших цепочек эффективность новой реализации не столь значительна, но все же выше исходной версии.
Интересным в новом предложении является улучшение для крупных сетей, которое значительно улучшает время. Стоит отметить, что в ядре Linux размер строк, обрабатываемых в memchr(), достигает 512 байт. В наших тестах прирост производительности для 512-байтных строк в ситуации, когда искомый символ находится в конце строки, это 20%.
Стоит отметить, что исходная версия memchr() реализована с использованием метода побайтового сравнения, который не полностью использует регистры на 64-битном или 32-битном процессоре.
Мы используем сравнение целых слов, чтобы процессор мог одновременно сравнивать 8 символов. Этот код основан на реализации Дэвида Лайта.
Мы создаем два файла для измерения производительности первого файла который содержит в среднем 10 символов перед символом назначения. Второй файл содержит не менее 1000 символов перед целевой персонаж.
Наша реализация "memchr()" немного лучше на первом тесте и почти в 4 раза быстрее оригинала реализация во втором тесте.
Тестирование ядра 5.18 с новым вариантом «memchr()» для 32-битной и 64-битной архитектуры проблем не выявил.
Что произойдет, если p не будет выровнен по 8 (или 4 для 32-битных целей) байт? Не все цели поддерживают невыровненные (эффективные) нагрузки, верно?
Я думаю, что это работает, если p не выровнен по 8 или 4 байтам. Допустим, строка 10 байт. Цикл for здесь будет искать первые 8 байтов. Если символ назначения находится в последних 2 байтах, второй цикл for найдет его. Это также работает на 32-битных машинах.
Общий прирост производительности еще не оценен подсистем ядра при использовании оптимизированного варианта «memchr()», а также не обсуждалось, следует ли переопределять реализацию (вызов функции memchr() встречается в коде ядра 129 раз, включая драйверы и файловые системы).
В конце концов Если вам интересно узнать об этом больше, вы можете проверить детали По следующей ссылке.