Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select2 is slow on opening #781

Closed
MgSam opened this Issue Jan 31, 2013 · 80 comments

Comments

Projects
None yet
@MgSam
Copy link

MgSam commented Jan 31, 2013

I'm finding Select2 is quite slow when opening its dropdown menu if the underlying select has a fair number of items. Am I right in guessing it is (re)creating the HTML/DOM for this dropdown each time it is invoked? Wouldn't it make more sense to cache this and only redraw it if the underlying select changes?

Here's an example:
http://jsfiddle.net/48wFG/1/

Thanks in advance.

@ivaynberg

This comment has been minimized.

Copy link
Contributor

ivaynberg commented Jan 31, 2013

you are right in your analysis.

its not possible to cache the dom because searching using the search field mangles it. instead, the default query function used when attached to selects should implement partial loading with infinite scrolling - just like server side though, albeit with a bigger page size.

will try to look into it when i have time.

@kevin-brown kevin-brown referenced this issue Feb 1, 2013

Closed

IE8 Slow #787

@DR9885

This comment has been minimized.

Copy link

DR9885 commented Feb 4, 2013

After taking a closer look at the code, I noticed a couple things causing these large performance hits on IE.

  1. Inside the "populateResults" method, DOM Manipluation is being done with the jQuery Library, which is great for readability, but poor for performance.

REF: http://www.artzstudio.com/2009/04/jquery-performance-rules/#limit-dom-manipulation

  1. There is never any caching, even if the select never changes (Unless I'm not aware of some setting to achieve this).
@sandrods

This comment has been minimized.

Copy link

sandrods commented Mar 1, 2013

+1

1 similar comment
@ximi

This comment has been minimized.

Copy link

ximi commented Mar 4, 2013

+1

@gazMac2

This comment has been minimized.

Copy link

gazMac2 commented Mar 5, 2013

@DR9885 Looks like you are correct with this. I did some tests and there was some real speed improvements doing that. However, I can't get that function to work quite right. Did you ever implement the changes in this function and would you share your code?

@MgSam

This comment has been minimized.

Copy link
Author

MgSam commented Mar 5, 2013

I agree that the list creation code should be rewritten to make the complete HTML in string form and then do a single JQuery call to make the actual DOM elements.

@DR9885

This comment has been minimized.

Copy link

DR9885 commented Mar 5, 2013

@gazMac2 I did spend some time with the code to make changes, but it looked more than just a quick change and sadly I don't have too much time available.

Also it does look like the plugin rebuilds the ENTIRE list anytime a user opens or filters. I wonder if we could cache some of the html & results, or even better maybe inject a Template Engine.

@vtt

This comment has been minimized.

Copy link

vtt commented Apr 1, 2013

+1

@bostondp

This comment has been minimized.

Copy link

bostondp commented May 2, 2013

+1

@ova2

This comment has been minimized.

Copy link

ova2 commented May 11, 2013

@DR9885 Great analysis. +1 for 1) and 2).

@albanomiguel

This comment has been minimized.

Copy link

albanomiguel commented Jun 7, 2013

Hi,

I am having exactly the same issue here which is even more severe on IE.

Is there any update on this? Are there any plan to fix this in a short term?

Thanks

@ivaynberg

This comment has been minimized.

Copy link
Contributor

ivaynberg commented Jun 7, 2013

short term you can write your own query function that retrieves options piecemeal.

@MgSam

This comment has been minimized.

Copy link
Author

MgSam commented Jun 18, 2013

Speaking of performance issues- I was looking through the source and I noticed it filters out duplicates by using an indexOf() function that searches for a matching entry through the array of entries. This is O(n^2) and really should be rewritten to use a hashtable instead.

        updateSelection: function (data) {
            var ids = [], filtered = [], self = this;

            // filter out duplicates
            $(data).each(function () {
                if (indexOf(self.id(this), ids) < 0) {
                    ids.push(self.id(this));
                    filtered.push(this);
                }
            });
            data = filtered;

            this.selection.find(".select2-search-choice").remove();
            $(data).each(function () {
                self.addSelectedChoice(this);
            });
            self.postprocessResults();
        }

There are a few other places indexOf() is used while looping through the list as well.

@ova2

This comment has been minimized.

Copy link

ova2 commented Jun 18, 2013

Also jQuery each is slower than a native loop. It is better to use a native loop.

var $data = $(data);
var length = $data.length;
for (var i=0; i < length; i++) {
   // access with. $data[i]
   ...
});

Almost every tutorial suggest to avoid each and push. push is slow too. So, this code (adding of a new element can be in a loop of course)

var myArray = [];
var newElement = "test element";
myArray[myArray.length] = newElement;

works faster than this one

var myArray = new Array();
var newElement = "test element";
myArray.push(newElement);
@ivaynberg

This comment has been minimized.

Copy link
Contributor

ivaynberg commented Jun 18, 2013

@MgSam @ova2 pull requests are welcome

@elaine97

This comment has been minimized.

Copy link

elaine97 commented Jun 20, 2013

+1

1 similar comment
@gregormelhorn

This comment has been minimized.

Copy link

gregormelhorn commented Jul 4, 2013

+1

@ash2osh

This comment has been minimized.

Copy link

ash2osh commented Aug 6, 2013

+2

@efib

This comment has been minimized.

Copy link

efib commented Aug 8, 2013

+1

1 similar comment
@kanfet

This comment has been minimized.

Copy link

kanfet commented Aug 13, 2013

+1

@jdecuyper

This comment has been minimized.

Copy link
Contributor

jdecuyper commented Aug 16, 2013

@ivaynberg: beside fixing the indexOf performance issue with a hashtable or similar, would it be a a good idea to use the each2 implementation for the iteration?

@ivaynberg

This comment has been minimized.

Copy link
Contributor

ivaynberg commented Aug 16, 2013

probably, but i dont think it will help much. what should really happen is that the rendering should be done in a string and then bound with data later. this is how it worked originally, but i made the mistake of refactoring it to make renderers more flexible. in 4.0 i will go back.

@czj

This comment has been minimized.

Copy link

czj commented Aug 16, 2013

Thanks a lot @ivaynberg that will be great :-)

@loginetsolutions

This comment has been minimized.

Copy link

loginetsolutions commented Sep 3, 2013

+1

2 similar comments
@funwithtriangles

This comment has been minimized.

Copy link

funwithtriangles commented Sep 13, 2013

+1

@kaldrenon

This comment has been minimized.

Copy link

kaldrenon commented Sep 13, 2013

+1

kevin-brown added a commit that referenced this issue May 27, 2014

Merge pull request #2360 from ycdtosa/master
changes on updateResults, populate by @cervengoc on #781

@kevin-brown kevin-brown removed this from the 3.5.0 milestone Jun 4, 2014

@BonnieDoug

This comment has been minimized.

Copy link

BonnieDoug commented Jul 13, 2014

I think related to this issue, I'm currently trying to load a large table (8800 Rows / 2.5mib) however it crashes. In Chrome F12 I get an error of:

POST http://localhost/web/app_dev.php/_entity_find 500 (Internal Server Error) main.js:3
k.cors.a.crossDomain.send main.js:3
n.extend.ajax main.js:3
(anonymous function)

(main.js is my compiled JS containing select2)

I have other select2 autocomplete fields on the same page searching smaller tables which work perfectly fine (a little slow but nothing major)

Looking in apache error.log I have this error:

[client ::1:55760] AH00124: Request exceeded the limit of 10 internal redirects due to probable     configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel     debug' to get a backtrace., referer: http://localhost/web/app_dev.php/user/prod/new

If I load the field as a plain choice field It loads fine, rather large and take around 7 seconds but loads all the same.

Using Symfony 2.4.* , Doctrine2 and the most up to date download of select2.

@BonnieDoug

This comment has been minimized.

Copy link

BonnieDoug commented Jul 18, 2014

Turns out my problem was solved by re building the table with a new id column and scraping the old one don't understand why but it solved it.

@kevin-brown

This comment has been minimized.

Copy link
Member

kevin-brown commented Dec 11, 2014

At this point Select2 should handle much better on large amounts of data.

#2848 just got merged in for Select2 3.5.3, which should improve the speed considerably.

Select2 4.0 had a major focus on fixing the jQuery performance issues (which I will write a post about at some point). #2743

If there are still any major bottlenecks in either version, reply back to this with a jsfiddle and the version number and we can continue making improvements. Until then, I think this is at a point where it can be closed.

@rikkert

This comment has been minimized.

Copy link

rikkert commented Dec 12, 2014

Great, thanks for letting us know.

On 11 dec. 2014, at 20:59, Kevin Brown notifications@github.com wrote:

Closed #781.


Reply to this email directly or view it on GitHub.

@webivation

This comment has been minimized.

Copy link

webivation commented Jul 20, 2015

Still seeing a slowdown (4.0) on over even a thousand datasets (using templates for results, which i'm sure adds to overhead).

What about a user friendly loading view? As soon as the user clicks show the dropdown with a loading gif, then when the data loads replace said gif with the data?

If would support large amounts of data being a little sluggish without confusing the user as to if anything is actually happening or not.

So we can use this I'm about to add this functionality myself.

@kevin-brown

This comment has been minimized.

Copy link
Member

kevin-brown commented Jul 20, 2015

I'm a fan of the idea of displaying some sort of "loading" message when Select2 is processing the results, I'd even be willing to make it the default behaviour when Select2 is running slow.

If someone gets a pull request going for it, we can discuss the idea in more detail.

As soon as the user clicks show the dropdown with a loading gif, then when the data loads replace said gif with the data?

Right now we have a "Seaching..." string which we use for this (with AJAX, usually) that I wouldn't mind bringing to a standard <select> if possible.

We dropped the old spinner gif while removing external image dependencies from Select2, and I'd rather keep it out.

@webivation

This comment has been minimized.

Copy link

webivation commented Jul 21, 2015

That sounds ideal, keeping the two UI experiences the same regardless of datasource. I'll look into that with my changes and make a pull request for it once I'm done for you to review.

@fk

This comment has been minimized.

Copy link
Member

fk commented Jul 22, 2015

Here's an issue tracking the missing loading image/spinner GIF: #3227 – I'll add my (incomplete) thoughts regarding the loading image over there.

@sebgos

This comment has been minimized.

Copy link

sebgos commented Nov 4, 2015

I saw this jsfiddles (http://jsfiddle.net/uLqc9/4/) however I have problem with < select >. How to implement this lady load with < select > and >100 options. I have issue when trying to test by emulate IE<11 in IE Developer Tools. For IE 11 works fine

@Sohorev

This comment has been minimized.

Copy link

Sohorev commented Mar 2, 2016

Select2 slowly on 1000+ items
But chosen not slowly

@sirNemanjapro

This comment has been minimized.

Copy link

sirNemanjapro commented Apr 8, 2016

Select 2, multiple, tag, two dropdowns - waiting time for opening a list of 40 items is 4-5 seconds (computer speed not a factor).

@galeroy

This comment has been minimized.

Copy link

galeroy commented Feb 17, 2017

It looks like upgrading to Select2 Version 3.5.3 improves speed for large lists.

What's not easy for me to find by looking around on the web:
What is the minimum version of AngularJS needed to support Select2 Version 3.5.3?

Thanks in advance if anyone knows this / where to find this info.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.