Comments 9
Хеш функция вместо того чтобы считать каждую букву строки, просто кастит указатель на данные строки к uint64_t keyArray[3] и считает сумму целых чисел.
… и вылетает по ошибке «доступ к невыровненной памяти» на процессоре ARM.
Если же вы об ASCIIZ-строках, то да, можно выравнивать их через прагмы, атрибуты или опции компилятора, но зачем?
ADD: Кроме того, подразумевается, что «быстрый хэш» будет использоваться как библиотека. Требовать от пользователя, чтобы все строки были выровнены на границу 8 байт — это перебор.
во-первых, если говорить именно про std::string, то выравнивание буфера зависит от реализации аллокатора, но едва ли оно будет меньше 8 байт.
Закладываться на особенности конкретной реализации — это прямой путь к большим проблемам в будущем.
Во-вторых, речь в статье не о хеш-функции (взятой, судя по всему, от балды), а об алгоритме кеширования. Эти вещи практически невисимы (производительность алгоритма кеширования может падать в случае плохой хеш-функции).
В-третьих, об алгоритме я вообще ни слова не сказал.
Предложенная реализация алгоритма кэширования имеет потенциальный баг, о котором я и сообщаю.
Друзья,
спасибо за активную переписку, которая навела меня на понимание сути ваших сомнений.
Вчера просто утром увидел коммент про проблемы на ARM процессорах (а такие у меня только на телефонах с Android есть), и решил сочетая полезное с полезным поднять стенд для Android (https://github.com/DimaBond174/android_cache — тут пока ещё только заголовок).
Вот, сегодня утром прочитал комментарии… и отвечаю:
Поведение ключа будь то числовой, строковый (или по музыке/видео/изображению/неведомому сферическому коню в вакууме) — это не вопрос библиотеки кеширования. Библиотеке кеширования (которая шаблон в одном .h файле) просто требуется от ключа реализация функций inline int compare (...) и inline uint64_t get_hash(...).
То как ключ себя ведёт со строками — частное личное внутреннее дело ключа и алгоритму кеширования до него дела нет. В частности предложенный расчёт хэш-а строки по uint64_t[3] в файле ikey2.h реализован так что при установке в ключ строки вызывается метод который гарантирует расширение строки до требуемого размера:
static constexpr int key_ElemNSizeKey_size = 3 * sizeof(uint64_t);
void setKey() {
len = data.length();
if (data.capacity() < key_ElemNSizeKey_size) {
data.reserve(key_ElemNSizeKey_size);
}
key.setKey(data.data());
}
Если по каким-либо причинам компилятор решит оптимизировать расширение строки, то всегда можно сделать memcpy в обнулённый массив uint64_t[3] на минимальное
из текущего размера строки и key_ElemNSizeKey_size.
Быстрый кэш на C/C++, потокобезопасность