Dynamic ComboBox values/options based on user-input

I want to implement a search functionality where a user is able to type some search string and then is shown a list of possible matches based on the search string. ComboBox looks like a good fit for this (?). I was trying to use the ComboBox with a custom AbstractBackendDataProvider, which takes the search string (filter) and executes the search. This is nice, because the fetchFromBackend method is called whenever something is typed in the ComboBox’s search field. Also it fires only a single query when typing multiple characters quickly (very usefult for my use-case). However, I am running into two problems:

  1. The sizeInBackend method is called first and at this point I simply do not know how many search matches there will be (there can be anything from lets say 0 to 10 matches)
  2. Upon entering a search string the ComboBox shows a little loading animation, and even when I am returning a fixed size list of e.g. five strings it seems to respond quite slowly

Is there a better approach for my use-case than using ComboBox this way? What is the recommended way to deal with the problem of not knowing the number of items to be shown? Any good workarounds here? Why is the UI so slow? Are there any ways to tune this a bit?

For example here is the code that uses a fixed list of three strings (and yields a rather slow ui experience):

 private class MyDataProvider extends AbstractBackEndDataProvider<String, String> {
        @Override
        protected Stream<String> fetchFromBackEnd(Query<String, String> query) {
            // apparently I am supposed to call these methods
            System.out.println("offset: " + query.getOffset());
            System.out.println("limit : " + query.getLimit());
            if (query.getFilter().isPresent()) {
                return Stream.of("a", "b", "c");
            } else {
                return Stream.of();
            }
        }

        @Override
        protected int sizeInBackEnd(Query<String, String> query) {
            if (query.getFilter().isPresent()) {
                return 3;
            } else {
                return 0;
            }
        }
    }