Увеличиваем производительность Sphinx BuildExcerpts
Posted in Performance, Sphinx Search, Tips And Tricks on August 7th, 2011 by Yaroslav Vorozhko – Be the first to commentEnglish version of this post.
Начиная с версии 2.0.1 в Sphinx появилась возможность параллельного построения поисковых сниппетов. Под параллельным построением имеется ввиду, что процесс обработки массива текста предназначенного для построения сниппетов будет распределен по нескольким CPU. Приведенная ниже реализация лучше всего подойдет системам в которых требуется генерировать сниппеты для сотен мегабайт текста.
Для распараллеливания процессов в Sphinx предусмотрена опция dist_threads, которая указывает searchd на сколько CPUs разбивать задачу. dist_threads используется как для обработки поисковых запросов в распределенных индексах, так и для обработки сниппетов, которые мы рассмотрим ниже.
Рассмотрим функцию SphinxAPI BuildExcerpt. По умолчанию функция BuildExcerpt в качестве первого параметра принимает массив текста для обработки,
но к сожалению такой вызов функции не использует параллельную обработку.
Но, начиная с версии 2.0.1, для BuildExcerpt был разработана новая опция load_files. load_files указывает Sphinx, что первый параметр функции BuildExcerpt должен содержать имена файлов, в которых должен находиться текст для обработки. Опция load_files совместно с опцией dist_threads позволяет Sphinx распаралеливать процесс построения сниппетов.
К сожалению у данной реализации есть узкое место - это необходимость использовать файловую систему. Так как, прежде чем генерировать сниппеты на основе файлов, надо эти файлы создать, а для жестких дисков это достаточно медленная операция. Поэтому, правильное решение, это создавать файлы в памяти, т.к. запись в память происходит в тысячи раз быстрее, чем на жесткий диск.
Для создания файлов в оперативной памяти в ядро Linux начиная с версии 2.4. включена файловой системой tmpfs, который мы и воспользуемся.
Файловая система
Для этого создадим директорию будущей системы и смонтируем ее.
-
mkdir /space
-
mount -t tmpfs -o size=1G,nr_inodes=10k,mode=0700 tmpfs /space
В данном примере права на запись будут только у владельца директории /space, а максимальный размер файловой системы будет установлен в 1Gb.
Модифицируем BuildExcerpts
-
function buildExcerptFile($documents, $options = array())
-
{
-
foreach($documents as $doc){
-
$file = "/space/".'snip_'.md5($doc).'_'.time();
-
file_put_contents($file, $doc);
-
$files[] = $file;
-
}
-
-
$client = new SphinxClient();
-
$client->setServer('localhost', 9312);
-
-
$res = $client->BuildExcerpts( $files, 'index', $keywords,
-
array(
-
'around'=>10,
-
'limit' => 300,
-
'load_files' => 1
-
)
-
);
-
-
foreach($files as $file){
-
unlink($file);
-
}
-
-
return $res;
-
}
Функция работает в три этапа:
- Первый. Записываем все документы в файлы, причем имена файлов выбираются так, чтоб не получилось коллизий.
- Второе. Вызываем функцию Sphinx BuildExcerpt, первым параметром передаем массив файлов вместо массива текста. А в третьем параметре указываем опцию load_files = 1
- Третий. Удаляем созданные файлы для очистки памяти.
Sphinx.conf
В разделе searchd добавляем следующую строку:
-
dist_threads = 2
dist_thread лучше делать равным количеству CPU в системе.
На моих тестовых данных, данная реализация работает в два раза быстрее «стандартного» вызова BuildExcerpts на системе с двумя CPU. Средний размер документа 1-3 Mb, количество документов для одной было равным 100, т.е. один вызов обрабатывал в среднем 200 Mb текста.
