Fix performance issue with word completion
When pasting many words with <a-p> we can end-up with a huge concatenated word and many selections, the previous code ended up iterating from each selection cursor to that word start and end to find the word under the cursor. This could lead to performance issue as each selection would trigger iteration on that huge word. This is unnecessary as word completion has a word length limit, so we now take it into account to avoid iterating to far from the cursor position.
This commit is contained in:
parent
b1745ee8d3
commit
3ae2a5c2f6
|
@ -86,9 +86,12 @@ InsertCompletion complete_word(const SelectionList& sels,
|
||||||
HashMap<StringView, int> sel_word_counts;
|
HashMap<StringView, int> sel_word_counts;
|
||||||
for (int i = 0; i < sels.size(); ++i)
|
for (int i = 0; i < sels.size(); ++i)
|
||||||
{
|
{
|
||||||
|
int len = 0;
|
||||||
|
auto is_short_enough_word = [&] (Codepoint c) { return len++ < WordDB::max_word_len && is_word_pred(c); };
|
||||||
|
|
||||||
Utf8It end{buffer.iterator_at(sels[i].cursor()), buffer};
|
Utf8It end{buffer.iterator_at(sels[i].cursor()), buffer};
|
||||||
Utf8It begin = end-1;
|
Utf8It begin = end-1;
|
||||||
if (not skip_while_reverse(begin, buffer.begin(), is_word_pred) and
|
if (not skip_while_reverse(begin, buffer.begin(), is_short_enough_word) and
|
||||||
begin < end) // (begin might == end if end == buffer.begin())
|
begin < end) // (begin might == end if end == buffer.begin())
|
||||||
++begin;
|
++begin;
|
||||||
|
|
||||||
|
@ -98,11 +101,14 @@ InsertCompletion complete_word(const SelectionList& sels,
|
||||||
prefix = buffer.substr(word_begin, end.base().coord());
|
prefix = buffer.substr(word_begin, end.base().coord());
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_while(end, buffer.end(), is_word_pred);
|
skip_while(end, buffer.end(), is_short_enough_word);
|
||||||
|
|
||||||
|
if (len <= WordDB::max_word_len)
|
||||||
|
{
|
||||||
StringView word = buffer.substr(begin.base().coord(), end.base().coord());
|
StringView word = buffer.substr(begin.base().coord(), end.base().coord());
|
||||||
++sel_word_counts[word];
|
++sel_word_counts[word];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct RankedMatchAndBuffer : RankedMatch
|
struct RankedMatchAndBuffer : RankedMatch
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,8 +21,6 @@ WordDB& get_word_db(const Buffer& buffer)
|
||||||
|
|
||||||
struct WordSplitter
|
struct WordSplitter
|
||||||
{
|
{
|
||||||
static constexpr CharCount max_word_len = 50;
|
|
||||||
|
|
||||||
struct Iterator
|
struct Iterator
|
||||||
{
|
{
|
||||||
Iterator(const char* begin, const WordSplitter& splitter)
|
Iterator(const char* begin, const WordSplitter& splitter)
|
||||||
|
@ -48,7 +46,7 @@ struct WordSplitter
|
||||||
utf8::to_next(m_word_end, end);
|
utf8::to_next(m_word_end, end);
|
||||||
++word_len;
|
++word_len;
|
||||||
}
|
}
|
||||||
if (m_word_begin == end or word_len < max_word_len)
|
if (m_word_begin == end or word_len < WordDB::max_word_len)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class Buffer;
|
||||||
class WordDB : public OptionManagerWatcher
|
class WordDB : public OptionManagerWatcher
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static constexpr CharCount max_word_len = 50;
|
||||||
|
|
||||||
WordDB(const Buffer& buffer);
|
WordDB(const Buffer& buffer);
|
||||||
~WordDB();
|
~WordDB();
|
||||||
WordDB(const WordDB&) = delete;
|
WordDB(const WordDB&) = delete;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user