Closed raRaRa closed 2 years ago
Here's a snippet that reproduces this issue:
for (let i = 0; i < 100; i++) {
updatedPeopleActions.push(
createAction({
name: `John${i} is a member in Team Test`,
icon: 'layers-three-01',
keywords: [
`John${i} is a member in ${i}`,
`Teams where John${i} is a member`,
]
.filter((word) => !!word)
.join(', '),
perform: () => console.log('Hello'),
})
);
}
In my actual code John${i}
is an actual person name and it's not repeating like that. But this code is enough to show how unresponsive kbar becomes with these actions.
Just type something like 'John is a ..." and it becomes very sluggish after typing "a".
Hey @raRaRa 👋
How are you building updatedPeopleActions
? ie; is the updatedPeopleActions
list getting rebuilt every time you type something into the search bar?
Here's an example with 1000 dynamically added actions, with 10 keywords each:
Can you try it with a similar query as I am using, where you use something like "Where bla is ...". Everything is fast for me as well until I use words such as "is".
Ah, I am able to reproduce it; it is due to command-score
.
So command-score
starts to degrade pretty heavily when the search term crosses ~ 15 characters and the data set is still quite large.
In your case, since a query of "John is a team member in team test etc.." will still match every single action, command-score
takes ~ 15ms for each action to resolve. That's not the best!
I think you can, for now, approach this with 2 temporary solutions:
John is a member in
can itself be a parent action, where children can be the resulting value.function useInternalMatches(filtered: ActionImpl[], search: string) {
const value = React.useMemo(() => {
// 1. trim down long words
const split = search.split(/\s/).map((word) => word.substring(0, 8));
// 2. just match against the last few
const refinedSearch = split.slice(split.length - 3).join(" ");
return {
filtered,
search: refinedSearch,
};
}, [filtered, search]);
const { filtered: throttledFiltered, search: throttledSearch } = useThrottledValue(value);
...
}
Again, these are temp solutions and we'll probably need to do a little further optimization within the lib.
Ah cool thanks, is it possible to bypass command-score completely, or replace it with my own function?
You can always just fork a copy of useMatches
and add your own custom matching logic! Pass the results to KBarResults
and you should be good to go.
Following up here: https://github.com/timc1/kbar/issues/255
When you have many actions (maybe 50-100ish), and some of them contain keywords such as "bla is a member in {teamName}", then kbar becomes almost unresponsive when typing "bla is a". This happens immediately after typing "a".
I have a feeling this is related to command score that is used under the hood. Would it be possible to somehow disable command score in kbar?
Thanks.