Gor
поиск подстроки.
yopp
Поиск подстроки это частный случай поиска пересечения множеств
Gor
в mongo поиск по фразе, если есть поиск аля "some phrase" идет по полному значению поля через стандартный посимвольный алгоритм sf или как его там
yopp
Скорее всего это уже в каком-нибудь бусте есть :)
Gor
вообщем я чета явно полез в зону где нихрена не знаю и что то новое сделал
yopp
Gor
straight forward - посимвольная проверка
Gor
проверяем 1 символ, потом второй и так далее
yopp
он там case sensitive?
yopp
если не указываешь, обе строки сначала приводятся к одному регистру?
Gor
как поиск происходит в 3.6 - получаются токены query выбираются все записи из базы по индексу токенов и потом пошел молотить каждую запись на стравнение query части сроки
Gor
если не указываешь то поиск идет strcasestr
yopp
а, окей. т.е. там strstr
Gor
для case sensetive - return haystack.find(phrase) != string::npos;
Gor
метод find на строке, но я не колупал может под обложкой strstr
yopp
окей. с бейзлайном понятно
yopp
в чём новшество?
Gor
смотри. для не фраз, они просто удовлетворяются stemm
Gor
тоесть если в поиске не фраза, сверяется stemm только.
Gor
в итоге основной нагруз только на сравнении фраз
Gor
у фраз есть инетерсный pattern - и вот это и есть частный случай которым можно оптимизировать. собственно у меня получился модифицированный sf за счет того, что я проверяю 1 и последний символ в первую очередь
Gor
и в итоге это работает быстрее%
yopp
Gor
фразы
Gor
в текстовом поле обьекта который индексировался
yopp
т.е. после текстового индекса задача сводится к поиску вхождения одной строки (токен из запроса) в другую (значения в документе)
Gor
это то как было сделано в FTS в монго
yopp
FTS это что?
Gor
тоесть да. на STAGE_TEXT_MATCH вытянуто значение по индексу обьекта и в поле - которое индексировалось они ищуют вхождение фразы
Gor
FullTextSearch- и кстати модуль у них в fts папке тоже)
yopp
так. а ты перед этим сравниваешь что?
yopp
если я правильно понял, то условно, у нас есть две строки «brown lazy fox jumps over lazy brown dog» и «lazy fox». первая строка это значение поля «foo» по которому построен text индекс. «lazy fox» это поисковый запрос по этому индексу.
есть обратный индекс с токенами brown, lazy, fox, jumps, over, lazy, dog, где каждый токен указывает на документ в котором он содержится. после фильтра по префиксам fox и lazy в этом индексе мы получили какой-то набор номеров документов, прочитали эти документы и остались мы с этими двумя строками.
дальше монга проверяет полноту вхождения (?) и ищет строку «lazy fox» в строке «brown lazy fox jumps over lazy brown dog» используя abseil string_view::find()
string_view::find() берёт и делает сравнение «brown lazy fox jumps over lazy brown dog» с «lazy fox», сдвигая индекс начала поиска на 1 и делая memcmp
yopp
так?
Gor
абсолютно верно. есть мелкие технические детали что за фоном. но логика верная
yopp
так
yopp
и где происходит озвученная оптимизиация?
Gor
конкретно сейчас именно с memcmp
yopp
получается тут? https://github.com/abseil/abseil-cpp/blob/38b704384cd2f17590b3922b97744be0b43622c9/absl/strings/internal/memutil.cc#L88
Gor
по сути да. немного по другому цикл построен но это вроде SF
Gor
я чего на это смотреть стал. на 37к записях цикл проверки на фразу занимает больше секунды
Gor
и это уже все 37К записи в памяти
yopp
так, разбираемся
match = static_cast<const char*>(
memchr(phaystack, pneedle[0], hayend - phaystack)
memchr ищет по первым (hayend - phaystack) байтам в phaystack на предмет совпадения с pneedle[0]. если совпадение найдено, возвращается указатель на первое совпадение
в этом случае этот указатель используется в memcmp(match, pneedle, neelen)
yopp
оптимизация заключается в том чтоб memcmp делать не по целой строке, а сначал сравнивать последний байт?
yopp
и делать memcmp по всей строке только если они совпали?
Gor
Gor
тут особенность еще в том, что мы по сути текст сравниваем. а у него часто бывает именно разница в окончаниях
yopp
ну вобщем-то если последний байт не совпадает, то вся строка тоже не совпадает )
yopp
если мы ищем полное совпадение
yopp
возможно действительно такая оптимизация может иметь место. но я практически уверен что дополнительная проверка негативно скажется на сравнении коротких строк
yopp
если где-то выше по стеку уже есть работа с размером строки, то наверное там можно сделать ветвление и найти такой размер, при котором оптимизация не ухудшает остальных кейсов
yopp
но это уже можно сказать квантовые масштабы и там побочные эффекты могут быть какие угодно) начиная от того что проверка в конце будет например приводить к тому что строка дважды будет складываться в кеш или что этот пайплайн как-то хитро оптимизируется. или что есть хитрая инструкция до которой всё оптимиризуется, которая в один присест это делает
yopp
в abseil вроде как есть бенчмарки, можно туда напихать своих кейсов и посмотреть
yopp
ещё есть тестфреймворк монговский
yopp
можно прогнать его несколько раз с патчем и без
yopp
но это делать надо на разных архитектурах
Gor
текс. малой ждет в садике. побег за ним. Я думаю оптимизацию этой части оставлю на следущий раз. спейчас и так уже не плохо получилось
yopp
метод поппера же. надо искать не подтверждение гипотезы, а опровержение :)
Gor
до
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 888,
"executionTimeMillis" : 20789,
"totalKeysExamined" : 473124,
"totalDocsExamined" : 435962,
после
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 887,
"executionTimeMillis" : 10876,
"totalKeysExamined" : 473124,
"totalDocsExamined" : 37162,
yopp
888 vs 887
Gor
и то во втором случае не прогретые данные с диска. обычно около 4с
Gor
888 vs 887
ага, я видел. при чем именно на этом запросе. надо вычленить тот отличный документ и посмотреть кто не прав. не удивлюсь если оригинальный алгорритм
yopp
ищет быстро но не очень точно)
Gor
надо докопать. возможно дубликат кстати
yopp
ну вобщем я бы искал подвох сначла
Gor
дя щя малого с садика заберу буду смотреть
yopp
у монги хороший тест сьюит
yopp
там сразу будет видно если что-то сломалось. а оно похоже сломалось
Gor
Gor
@dd_bb прикинь
Gor
в оригинальном коде ошибка
Gor
false positive на "Gas Stationclose" при поиске "Gas Station"
yopp
точно ли ошибка?
Gor
всмысле считается ли это фразой?
yopp
да
yopp
посмотри блейм
Gor
git blame?