Custom search bar speed issues

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
I'mHereToBeHelped
Earned a small fee
Earned a small fee
Posts: 20
Joined: Wed Jun 01, 2022 5:49 pm

Custom search bar speed issues

Post by I'mHereToBeHelped »

I'm making a custom search bar with wxTextCtrl and upon inputting text inside it (using bind), it checks inside a nested vector for matching strings and displays these strings below the search bar on another custom panel.

The vector it checks inside looks something like this:

Code: Select all

std::vector<std::vector<std::unordered_map<std::string, std::variant<std::string, std::vector<std::string>>>>>
Now as you can imagine I have to write a lot of for loops to "get down" to the strings and see if they're a match for the input, which means a lot of for loops.

This causes the wxTextCtrl to lag when I put text inside (it waits till all the loops are finished to display the text inside the wxTextCtrl), I want the wxTextCtrl to ignore whether or not the for loops are finished. Like in Google where you can type as fast as you want with no display and the autocomplete results try to "catch up" and guess what you're looking for and not the other way around.

One way I can think of doing this is stopping the search and restarting it if a new text or character is typed (right now it waits to process every stroke typed till all the for loops have finished and then process any new keystrokes), I don't know how to do this though. This might be a bit tough so any help is nice.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Custom search bar speed issues

Post by doublemax »

How many strings are there?

The structure looks quite complicated, can you explain what it does?

Do you only match the beginning of the string, or the whole string?

Common solution:
When the text changes, don't start searching immediately. Instead start a timer (e.g. with half a second timeout) and only when the timer times out, perform the search. If the user types another key before the timer fires, the timer will only be restarted. The result is that the search will only happen, if the user didn't type anything for half a second.

With threads:
Move the search code to a secondary thread, so that you can receive new key events while the search runs. If the text changes, just set a flag which will be checked in the search loop of the thread. If the flag is set, it will just restart with the new value.

Use a database:
A database like sqlite has optimizations for full text search. It will most likely be much faster than your manual loop over all strings.
Use the source, Luke!
I'mHereToBeHelped
Earned a small fee
Earned a small fee
Posts: 20
Joined: Wed Jun 01, 2022 5:49 pm

Re: Custom search bar speed issues

Post by I'mHereToBeHelped »

When the results show up it's not exactly a string, It's a panel with a bunch of strings on it, think of it like how a list of emails are shown on something like gmail or yahoo. So there are a lot of strings (0-200+ strings if not more depending on what is searched).

It shows info like sender name, email, email content, time sent, title and all that jazz all on individual panels inside a bigger panel. It pretty much does nothing else other than show that information

It matches based on the beginning of the string (so if "a" is searched "alpha" might pop up in the results and other words that start with "a")

For threads what do you mean by a "flag"

Also thank you for everything you do. I see that you've been on here for years, helping people out. it's really cool
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Custom search bar speed issues

Post by doublemax »

I'mHereToBeHelped wrote: Tue Aug 09, 2022 10:01 pm When the results show up it's not exactly a string, It's a panel with a bunch of strings on it, think of it like how a list of emails are shown on something like gmail or yahoo. So there are a lot of strings (0-200+ strings if not more depending on what is searched).
200 is not much, on modern hardware it should be easily possible to search through them in realtime. I suspect the hierarchy of containers is not optimal for searching. Can you show the code of your search loop?

If the data can't be restructured, you'll need something like an index in a database. A flat vector containing the string the user can search for, together with a hint on how to find it in the "real" data structure ( i can't be more specific here, as i don't know how your data is organized).
Use the source, Luke!
I'mHereToBeHelped
Earned a small fee
Earned a small fee
Posts: 20
Joined: Wed Jun 01, 2022 5:49 pm

Re: Custom search bar speed issues

Post by I'mHereToBeHelped »

Well the results display panel loads fine, its just a very minor problem that I think I'll be able to fix with the timer (since its already pretty fast just looks buggy).

The main problem is the search bar not loading in new keystrokes though, I think threads will solve the issue, although not sure how to apply them properly. This is a template of how I have things set up now. When I run this and type something in the search bar it freezes for a while and then crashes

Code: Select all


SearchBar->Bind(wxEVT_TEXT, &MyFrame::SearchBarTextChange, this);



void MyFrame::SearchBarTextChange(wxCommandEvent& event) {

// sees if searchbar's input matches anything in the vector 
 
 SearchResultsCreate(); // std::thread thread_object(&MyFrame::SearchResultsCreate, this); thread_object.join();  is this how I do it?
 
}

void MyFrame::SearchResultsCreate(){

// creates results display panel

}


User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Custom search bar speed issues

Post by doublemax »

I'mHereToBeHelped wrote: Wed Aug 10, 2022 6:09 am Well the results display panel loads fine, its just a very minor problem that I think I'll be able to fix with the timer (since its already pretty fast just looks buggy).
I think the timer will solve the keyboard issue, too.

But if you decide to use a thread, it's not as simple as in your template.

- you can't use join(), as this will wait for the thread to finish, blocking the main thread

- if you receive another key stroke while the thread is running, you either need to destroy the already running thread, or tell it to stop and restart the search with the new search string

- you can't fill / create the actual gui from inside the thread. All access to gui elements must happen in the main thread.
Use the source, Luke!
I'mHereToBeHelped
Earned a small fee
Earned a small fee
Posts: 20
Joined: Wed Jun 01, 2022 5:49 pm

Re: Custom search bar speed issues

Post by I'mHereToBeHelped »

I think I came up with a solution that might bypass the threading and adds to the timer idea.

Before each

Code: Select all

for 
loop starts in the functions that create the display panel and match the strings with the search input, I check if the input has been changed, if it has changed I make it

Code: Select all

return
. I also add the timer idea that you mentioned before any of the functions or anything has been done. Is this smart or am I missing something?
Post Reply