Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cpp_src/core/ft/ft_fast/dataholder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,15 @@ size_t DataHolder<IdCont>::GetMemStat() {
for (auto& w : words_) {
res += sizeof(w) + w.vids.heap_size();
}
res += wordsCharsLen_.capacity() * sizeof(wordsCharsLen_[0]);

@MadSchemas MadSchemas Jul 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wordsCharsLen_[0] is unsafe from ASAN/Debug standpoint. Size of value_type would be better

return res;
}

template <typename IdCont>
void DataHolder<IdCont>::Clear() {
IDataHolder::Clear();
words_.resize(0);
wordsCharsLen_.resize(0);
}

template <typename IdCont>
Expand All @@ -110,10 +112,12 @@ void DataHolder<IdCont>::StartCommit(bool complete_updated) {

Clear();
words_.clear();
wordsCharsLen_.clear();
lastStepWords_.clear();
} else if (NeedRecommitLast()) {
status_ = RecommitLast;
words_.erase(words_.begin() + steps.back().wordOffset_, words_.end());
wordsCharsLen_.erase(wordsCharsLen_.begin() + steps.back().wordOffset_, wordsCharsLen_.end());

for (auto& word : words_) {
word.RestoreState();
Expand Down
16 changes: 16 additions & 0 deletions cpp_src/core/ft/ft_fast/dataholder.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ class [[nodiscard]] IDataHolder {
template <typename IdCont>
class [[nodiscard]] DataHolder : public IDataHolder {
public:
using WordCharsLenType = uint16_t;

explicit DataHolder(FTConfig* c);
void Process(VDocsTexts& vdocsTexts, const std::vector<uint32_t>& vdocsIds, size_t numDocsTotal, size_t fieldSize, bool multithread,
std::vector<h_vector<float, 3>>& wordsCounts) final;
Expand All @@ -193,6 +195,19 @@ class [[nodiscard]] DataHolder : public IDataHolder {
void Clear() override final;
std::vector<PackedWordEntry<IdCont>>& GetWords() noexcept { return words_; }
const std::vector<PackedWordEntry<IdCont>>& GetWords() const noexcept { return words_; }
void ReserveWords(size_t capacity) {
words_.reserve(capacity);
wordsCharsLen_.reserve(capacity);
}
void AddWordCharsLen(WordCharsLenType charsLen) {
assertrx_dbg(wordsCharsLen_.size() < words_.size());
wordsCharsLen_.emplace_back(charsLen);
}
WordCharsLenType GetWordCharsLen(WordIdType id) const noexcept {
assertrx(!id.IsEmpty());
assertrx(id.b.id < wordsCharsLen_.size());
return wordsCharsLen_[id.b.id];
}
PackedWordEntry<IdCont>& GetWordEntry(WordIdType id) noexcept {
assertrx(!id.IsEmpty());
assertrx(id.b.id < words_.size());
Expand All @@ -204,6 +219,7 @@ class [[nodiscard]] DataHolder : public IDataHolder {
return words_[id.b.id];
}
std::vector<PackedWordEntry<IdCont>> words_;
std::vector<WordCharsLenType> wordsCharsLen_;
};

} // namespace reindexer
6 changes: 3 additions & 3 deletions cpp_src/core/ft/ft_fast/dataprocessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,7 @@ typename DataProcessor<IdCont>::WordsVector DataProcessor<IdCont>::insertIntoSuf
word_hash wh;

suffix.reserve(words_um.size() * 20, words_um.size());
if (words.empty()) {
words.reserve(words_um.size());
}
holder.ReserveWords(words.size() + words_um.size());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

words.size() + words_um.size() does not looks correct for the cases, when words already contain something. Actually, current logic may overreserve here up to 2 times


WordsVector found;
found.reserve(words_um.size());
Expand All @@ -99,7 +97,9 @@ typename DataProcessor<IdCont>::WordsVector DataProcessor<IdCont>::insertIntoSuf
}
found.emplace_back(keyIt.first);

const auto charsLen = static_cast<typename DataHolder<IdCont>::WordCharsLenType>(getUTF8StringCharactersCount(keyIt.first));
words.emplace_back();
holder.AddWordCharsLen(charsLen);
pos = holder.BuildWordId(id);
suffix.insert(keyIt.first, pos);
holder.lastStepWords_[wh(keyIt.first)].emplace_back(pos);
Expand Down
10 changes: 6 additions & 4 deletions cpp_src/core/ft/ft_fast/selecterimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ ft::TermResults<IdCont> Selector<IdCont>::buildTermResults(const FtDSLEntry& ter
size_t matched = 0, vids = 0, excludedCnt = 0;
const std::string& patternUtf8 = variant.PatternUtf8();
const size_t patternBytes = patternUtf8.length();
const auto patternChars = static_cast<uint32_t>(getUTF8StringCharactersCount(patternUtf8));
for (const auto& step : holder_.steps) {
if (variant.lowRelevance && totalVids >= lowRelevanceLimit) {
break;
Expand Down Expand Up @@ -329,11 +330,12 @@ ft::TermResults<IdCont> Selector<IdCont>::buildTermResults(const FtDSLEntry& ter
break;
}

// ToDo fix it (broken for russian utf8 symbols)
const int matchDif = std::abs(long(word.length() - variant.PatternUtf8().length() + wordLengthBeforePattern));
const uint32_t wordChars = holder_.GetWordCharsLen(wordId);
const uint32_t unmatchedChars = wordChars > patternChars ? wordChars - patternChars : 0;
const float boost = std::max(getTermBoost(std::string(word)), variant.boost);
const float decreasePenalty = static_cast<float>(holder_.cfg_->partialMatchDecrease * matchDif) /
std::max<float>(variant.PatternUtf8().length(), kMinPartialMatchDenominator);
const float decreasePenalty =
(static_cast<float>(holder_.cfg_->partialMatchDecrease) * static_cast<float>(unmatchedChars)) /
static_cast<float>(std::max(patternChars, kMinPartialMatchDenominator));
float proc = std::max<float>(variant.proc - decreasePenalty, isPrefix ? rankingCfg.PrefixMin() : rankingCfg.SuffixMin());
proc = std::min<float>(proc, variant.proc);
if (boost > 0.0f) {
Expand Down