Changeset - 190cb30841de
[Not reviewed]
default
0 4 0
Mads Kiilerich - 9 years ago 2016-07-28 16:34:49
madski@unity3d.com
branches: fix performance of branch selectors with many branches - only show the first 200 results

The way we use select2, it will cause browser performance problems when a
select list contains thousands of entries. The primary bottleneck is the DOM
creation, secondarily for the query to filter through the entries and decide
what to show. We thus primarily have to limit how many entries we put in the
drop-down, secondarily limit the iteration over data.

One tricky case is where the user specifies a short but full branch name (like
'trunk') but many other branches contains the same string (not necessarily at
the beginning, like 'for-trunk-next-week') which come before the perfect match
in the branch list. It is thus not a solution to just stop searching when a
fixed amount of matches have been found.

Instead, we limit the amount of ordinary query matches, but always show all
prefix matches. We thus always have to iterate through all entries, but we
start using the (presumably) cheaper prefix search when the limit has been
reached.

There is no filtering initially when there is no query term, so that case has
to be handled specially.

Upstream select2 is now at 4.x. Upgrading is not trivial, and getting this
fixed properly upstream is not a short term solution. Instead, we customize our
copy. The benefit from this patch is bigger than the overhead of "maintaining"
it locally.
4 files changed with 25 insertions and 4 deletions:
0 comments (0 inline, 0 general)
kallithea/public/js/select2/select2.js
Show inline comments
 
@@ -1097,7 +1097,13 @@ the specific language governing permissi
 

	
 
                        // collect the created nodes for bulk append
 
                        var nodes = [];
 
                        for (i = 0, l = results.length; i < l; i = i + 1) {
 

	
 
                        // Kallithea customization: maxResults
 
                        l = results.length;
 
                        if (query.term.length == 0 && l > opts.maxResults) {
 
                            l = opts.maxResults;
 
                        }
 
                        for (i = 0; i < l; i = i + 1) {
 

	
 
                            result=results[i];
 

	
 
@@ -1138,6 +1144,10 @@ the specific language governing permissi
 
                            nodes.push(node[0]);
 
                        }
 

	
 
                        if (results.length >= opts.maxResults) {
 
                            nodes.push($('<li class="select2-no-results"><div class="select2-result-label">Too many matches found</div></li>'));
 
                        }
 

	
 
                        // bulk append the created nodes
 
                        container.append(nodes);
 
                        liveRegion.text(opts.formatMatches(results.length));
 
@@ -1161,16 +1171,25 @@ the specific language governing permissi
 

	
 
            if (select) {
 
                opts.query = this.bind(function (query) {
 
                    // Kallithea customization: maxResults
 
                    var data = { results: [], more: false },
 
                        term = query.term,
 
                        children, placeholderOption, process;
 
                        children, placeholderOption, process,
 
                        maxResults = opts.maxResults || -1,
 
                        termLower = term.toLowerCase();
 

	
 
                    process=function(element, collection) {
 
                        var group;
 
                        if (element.is("option")) {
 
                          if (collection.length < maxResults) {
 
                            if (query.matcher(term, element.text(), element)) {
 
                                collection.push(self.optionToData(element));
 
                            }
 
                          } else {
 
                            if (element.text().toLowerCase().indexOf(termLower) == 0) {
 
                                collection.push(self.optionToData(element));
 
                            }
 
                          }
 
                        } else if (element.is("optgroup")) {
 
                            group=self.optionToData(element);
 
                            element.children().each2(function(i, elm) { process(elm, group.children); });
kallithea/templates/changelog/changelog.html
Show inline comments
 
@@ -308,7 +308,7 @@ ${self.repo_context_bar('changelog', c.f
 
                // change branch filter
 
                $("#branch_filter").select2({
 
                    dropdownAutoWidth: true,
 
                    minimumInputLength: 1,
 
                    maxResults: 50,
 
                    sortResults: branchSort
 
                    });
 

	
kallithea/templates/files/files.html
Show inline comments
 
@@ -233,7 +233,7 @@ $(document).ready(function(){
 
    // change branch filter
 
    $("#branch_selector").select2({
 
        dropdownAutoWidth: true,
 
        minimumInputLength: 1,
 
        maxResults: 50,
 
        sortResults: branchSort
 
        });
 

	
kallithea/templates/pullrequests/pullrequest.html
Show inline comments
 
@@ -202,6 +202,7 @@ ${self.repo_context_bar('showpullrequest
 

	
 
      $("#org_ref").select2({
 
          dropdownAutoWidth: true,
 
          maxResults: 50,
 
          sortResults: branchSort
 
      });
 
      $("#org_ref").on("change", function(e){
 
@@ -217,6 +218,7 @@ ${self.repo_context_bar('showpullrequest
 

	
 
      $("#other_ref").select2({
 
          dropdownAutoWidth: true,
 
          maxResults: 50,
 
          sortResults: branchSort
 
      });
 
      $("#other_ref").on("change", function(e){
0 comments (0 inline, 0 general)