Pull to refresh

Sphinx: увеличиваем максимальный размер MVA

Reading time2 min
Views2.6K
Добрый день всем.

Недавно столкнулся с интересной проблемой, связанной с апдейтом MVA (multi value attributes).

Начальные условия:
  • sphinx-1.10-beta
  • sphinx php api

В рамках поставленной задачи мне нужно было реализовать on-a-fly апдейты mva аттрибутов. С начала всё показалось достаточно просто – берём функцию UpdateAttributes() из php-шной API и пишем нужные апдейты. Написал нужную обёртку, стал тестить – все отлично работает. Даже как то не поверилось что так быстро получилось – значит где то есть подвох. Начал тестить, так сказать, с фанатизмом – и подвох всплыл практически сразу.

При попытке запихнуть в MVA аттрибут массив, содержащий более 1022 значений, клиент отваливался с ошибкой “out of pool memory on MVA update”. Стал гуглить. Оказалось проблема эта не новая, и как возможное решение предлагают изменить параметр mva_updates_pool в sphinx.conf.

Попробовал с различными значениями. Но какое бы я значение там не ставил, ошибка появлялась снова и снова.

Решил копнуть глубже и посмотреть исходники – благо когда то писал на С.
Пригласил друга (решил воспользоваться практкой экстремального программирования), взяли пиво, и засели за дебаг исходников. После 2 часов дебага и некоторого колличества выпитого пива проблема была найдена.

Оказалось что в sphinx.cpp существует ещё одна проверка, параметры которой нельзя изменить из конфига, а именно:
int CSphArena::RawAlloc ( int iBytes )
{
    CheckFreelists ();
    if ( iBytes<=0 || iBytes>( ( 1 << MAX_BITS ) - (int)sizeof(int) ) ) {
        return -1;
    }
   …
}


iBytes – это собственно колличество байтов, которые будут выделенны в нашем случае под MVA аттрибут. А условие iBytes>( ( 1 << MAX_BITS ) — (int)sizeof(int) ) собственно представляет собой ограничение сверху. Говоря проще – переменная MAX_BITS отвечает за сдвиг. Т.е. IBytes сравнивается с 2^MAX_BITS — 4 (для 32-разрядной ) и с с 2^MAX_BITS — 2 для 16 разрядной. Значение MAX_BITS захардкодженно и равно 12. Таким образом, можно посчитать максимальное колличество int-овых значений которые можно запихнуть в MVA аттрибут. Считаем что у нас int занимает 4 байта. 4092/4 = 1023. Вот мы и получили наш предел.

Таким образом увеличивая значение MAX_BITS мы можем увеличить максимальную длинну MVA аттрибута. Жаль что он в коде объявлен как константа, т.е. мы не можем указать его в конфиге не правя исходники. Т.е. Пришлось увеличить эту константу и пересобрать заново.

Но самое главное – проблема решена.
Tags:
Hubs:
+20
Comments2

Articles

Change theme settings