Skip to content
This repository has been archived by the owner on Oct 2, 2019. It is now read-only.

Performance issues #88

Open
filipedeschamps opened this issue Jun 25, 2014 · 38 comments
Open

Performance issues #88

filipedeschamps opened this issue Jun 25, 2014 · 38 comments

Comments

@filipedeschamps
Copy link

Guys, we are suffering some serious performance issues. Does anyone know what is this $select.isActive(this) ?

Performance problem

@dimirc
Copy link
Contributor

dimirc commented Jun 28, 2014

I can't find it, can you upload an example or point where on the src its used?

@dimirc
Copy link
Contributor

dimirc commented Jul 10, 2014

Seams like this is related to #49 code

@DKirwan
Copy link

DKirwan commented Oct 3, 2014

Having the same issue. The batarang chrome developer tools extension (https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk?hl=en) exposes this issue. Removing the code that highlights the list item that you're hovering over improves performance noticeably, but it is still very slow. Doesn't appear to be related to #49.

See line 903 in dist/select.js for more info.

$templateCache.put("selectize/choices.tpl.html","<div ng-show=\"$select.open\" class=\"ui-select-choices selectize-dropdown single\"><div class=\"ui-select-choices-content selectize-dropdown-content\"><div class=\"ui-select-choices-group optgroup\"><div ng-show=\"$select.isGrouped\" class=\"ui-select-choices-group-label optgroup-header\">{{$group.name}}</div><div class=\"ui-select-choices-row\" ng-class=\"{active: $select.isActive(this)}\"><div class=\"option ui-select-choices-row-inner\" data-selectable=\"\"></div></div></div></div></div>");

@askhogan
Copy link

askhogan commented Dec 3, 2014

I saw the same thing in my app. I removed the isActive component and still have the same performance problem. It seems that if you load more than 10 ui select directives on the same page, the page becomes frozen for 5-6 seconds. I am using Mac OSX with the latest version of chrome.

I believe the performance issues are due to the ng-repeat mechanism in the ui-select-choices directive. I commented out this section of the code and the app became responsive again. It appears that the select dropdown list of choices is getting processed immediately, instead of when it is clicked on. If you have (several choices * several select-ui search boxes) on the same page it will slow down page load tremendously. I believe the solution is to delay the processing of the dropdown choices until a select-ui search box is clicked on, but I am still investigating...

The project I am using this with has one ui-select box per user. For large accounts with 50-150 users, loading can take about 15 - 30 seconds or cause chrome page to crash.

@jurintalu
Copy link

Any update on this? Same performance issues here aswell.

@askhogan
Copy link

askhogan commented Dec 8, 2014

This is not a permanent fix, but what I did was created a ng:if where I disabled the angular ui-select if the object was empty (e.g. no options selected). So for the directive to render a user must press on a button and then the UI renders. This prevents about 80% of the ui-selects from rendering on page for me and solved the problem.

My case is multi-select just to be clear.

Here is some sample code

<ui-select ng:if="user.hasExtensions"
///
</ui-select>   
                      <span ng:if="!user.hasExtensions"
                               ng:click="user.hasExtensions = true; refreshPlaceholder();"
                               class="btn-info-callinize"><i
                                     class='icon-plus-sign icon-white'></i></span>

@jurintalu
Copy link

Thanks but I have only one ui-select with roughly a thousand options. On IE9 it is pretty much unusable.

@gjoliver
Copy link

gjoliver commented Jan 8, 2015

yeah guys, this is really bad.
I have only 1 select with maybe 500 entries. And it's super slow.
any idea where the problem may be?

@gjoliver
Copy link

gjoliver commented Jan 9, 2015

ok I worked around this by doing repeat="...... | limitTo: 100", so we don't show a huge list of items.

@oaprograms
Copy link

@gjoliver
limitTo solves the speed issue, but it would be even nicer if remaining items could be appended automatically when the list is scrolled to bottom.

@rogerfar
Copy link

Any update on this? This is kind of a dealbreaker for me. I am migrating from Kendo, and have a dropdown with over 5000 items. In Kendo it opens, loads and filters in ms, in ui-select it's sluggish and often freezes the browser.

@aturkelson
Copy link

I'm having the same issue with around 500 items. Sometimes the performance gets so bad that the browser actually crashes!

@KevinPHughes
Copy link

Also a problem for me. I can't do the limitTo: 'myNumber' trick because it doesn't allow previously selected items to be pre-populated unless they're within the first 'myNumber' of my source.

@mareczek
Copy link
Contributor

Very recently (~ week ago) performance dropped even further. I have problems with a list of 103 items.

@adamkidder
Copy link

I recently switched from ui-select to angular-selectize due to performance. I'm dealing with lists of ~500 entries each and typing to filter is unacceptably slow.

@buremba
Copy link

buremba commented Mar 24, 2015

@mareczek +1

@vitto32
Copy link

vitto32 commented Mar 25, 2015

what about "suspending" the watchers instead of using ngIf (which stresses DOM on long lists)?
something like: https://coderwall.com/p/d_aisq/speeding-up-angularjs-s-digest-loop

@igorlino
Copy link

+1

@pitieu
Copy link

pitieu commented Apr 22, 2015

The performance issues are due to the ng-repeat mechanism in the ui-select-choices directive. Like askhogan said the dropdown list are getting processed immediately.
Also i added a custom filter and whenever i hover over a dropdown list item, it calls filter for every item in the dropdown list and every time i hover over another item it renders the filter again for every single item in the dropdown list. (at 20 items it already starts to get slow)

@vitto32
Copy link

vitto32 commented Apr 22, 2015

The performance issues are due to angular design who makes you build slow apps e and slow components. It's a sad lesson I've learned using ui-select and trying to make it faster for my use case (country dropdowns). In my next project I'll probably look elsewhere (aurelia.io, react, etc..).

@pitieu the hover problem is maybe the easieast to fix in the "angular way". The ng-mouseenter (as any other angular directive or service) calls a full scope digest while a $select digest should be enough, as far as activeIndex is not intended to be used outside the dropdown scope.
But that's just a little part of the problem. Both limitTo and infinite scrolling are possible workarounds but they come at a cost in terms of usability and more code to maintain and debug.

The way I solved my specific use case is a dirty hack. I've replaced the ng-repeat with a loop that rebuilds the entire dropdown content as a string. I don't know if this approach can be used by ui-select itself without breaking some piece of code (it probably would).

@brondavies
Copy link

Wow, this is a really old thread with no milestone set! Thanks for the vote of confidence. 😕

@igorlino
Copy link

I think in general, github should enable voting per issue, to make transparent where most problems are or what users are most interested in. (of course the motivation/drive of every open source project is always different)

I can imagine many would be voting for this issue.

@brondavies
Copy link

@igorlino most people just use a 👍 comment to increase interest or resurrect old issues but I agree that this seems like more of a work-around than a feature. Just as well, you can "subscribe" to issues without directly making a comment and this demonstrates increased community interest in resolving issues.

@oshai
Copy link

oshai commented Sep 21, 2015

I think this is related: #389

@jtheoof
Copy link

jtheoof commented Sep 22, 2015

👍 I am also stunned by the slow performance, even on small arrays (< 300 items).

@ZoharLiran
Copy link

Seeing the same issue 👍

@dimirc
Copy link
Contributor

dimirc commented Sep 28, 2015

With #1211 there should be some improvement

@drewfreyling
Copy link

@dimirc there is but not enough to close these issues.

@pascalcarmoni
Copy link

To activate the dropdown select choice only after x letter are typed :

<ui-select-choices refresh="CheckCity($select.search)" refresh-delay="400"
Add filter

| limitTo: limitcitysearch"

Than you have :
<ui-select-choices refresh="CheckCity($select.search)" refresh-delay="400" repeat="item.id as item in vm.territories | filter: {city: $select.search} | limitTo: limitcitysearch">

In controller

$scope.limitcitysearch = 5000; //Init with no limite : to see a previous selected valued in database (edit mode)

        vm.CheckCity = function (CityTyped) {
            if (CityTyped.length >= 1) {
                $scope.limitcitysearch = 100;
            }
            else {
              $scope.limitcitysearch = 0;
            }
        }

@jasonbrandt42
Copy link

Is there an option to load only first 100 then load more as the user scrolls down?

@lbolla
Copy link

lbolla commented Mar 16, 2016

I am affected by this issue, too.

@sgpalit
Copy link

sgpalit commented Apr 4, 2016

Anybody that will solve this problem?

@igorlino
Copy link

igorlino commented Apr 5, 2016

Sad to say, but after applying all hacks that I could, including the scrolling filter trick, it was simply not sufficient. So some radical change had to be done...

What did work, and is quite quite performant was to simply switch to another component https://github.com/machineboy2045/angular-selectize

The disadvantage is that is a wrapper to a jquery based component, and does not offer all the themes options.

The advantages are that the directive is very very small, the configuration of it is mostly not in the HTML but in the controller, so the HTML is much easier to read, configure and REUSE.

As the select does not know anything about angular, it also does not inherit Angular performance problems.
selectize is very robust and has tons of options to adapt itself quite well to the angular lifecycle.

@user378230
Copy link
Contributor

@igorlino your update appears to be related to angular-selectize library not ui-select. It doesn't appear to help resolve any problems with performance or add meaningful information to what has already been drescribed.


Can I ask that future posters contribute meaningful updates to the issue.

Useful updates:

  • Demo plunkrs would be helpful to profile against
  • Profiling results which show where code is getting slowed down
  • PRs addressing bottlenecks in code

+1's are not helpful (please use github reactions), open issues are still outstanding and need to be addressed.

Again, PRs are more help than posting in issues.

Thanks all! 😺

@user378230
Copy link
Contributor

Currently ctrl.items is searched everytime isActive is called which may be expensive if ctrl.items.length>1000.

ctrl.isActive = function(itemScope) {
    // ...
    var itemIndex = ctrl.items.indexOf(itemScope[ctrl.itemProperty]);
    var isActive =  itemIndex == ctrl.activeIndex;
    // ...
  };

It might be possible to improve isActive() by storing an activeItem rather than comparing on index every time.

Which would reduce isActive() to:

// Gets active item from active index somehow, needs to 
// account for changes to activeIndex and activeIndex value 
// when using tagging
var activeItem = getActiveItem();

ctrl.isActive = function(itemScope) {
    // ...
    var item = itemScope[ctrl.itemProperty];
    var isActive =  item == activeItem;
    // ...
  };

@user378230 user378230 mentioned this issue Apr 5, 2016
8 tasks
@itchyny
Copy link

itchyny commented May 26, 2016

The filtering logic of ui-select is heavy. The $scope.$apply and $timeout on the keydown event trigger $rootScope.$digest, which forces dirty check on the every watch expression (code:

ctrl.searchInput.on('keydown', function(e) {
var key = e.which;
if (~[KEY.ENTER,KEY.ESC].indexOf(key)){
e.preventDefault();
e.stopPropagation();
}
// if(~[KEY.ESC,KEY.TAB].indexOf(key)){
// //TODO: SEGURO?
// ctrl.close();
// }
$scope.$apply(function() {
var tagged = false;
if (ctrl.items.length > 0 || ctrl.tagging.isActivated) {
_handleDropDownSelection(key);
if ( ctrl.taggingTokens.isActivated ) {
for (var i = 0; i < ctrl.taggingTokens.tokens.length; i++) {
if ( ctrl.taggingTokens.tokens[i] === KEY.MAP[e.keyCode] ) {
// make sure there is a new value to push via tagging
if ( ctrl.search.length > 0 ) {
tagged = true;
}
}
}
if ( tagged ) {
$timeout(function() {
ctrl.searchInput.triggerHandler('tagged');
var newItem = ctrl.search.replace(KEY.MAP[e.keyCode],'').trim();
if ( ctrl.tagging.fct ) {
newItem = ctrl.tagging.fct( newItem );
}
if (newItem) ctrl.select(newItem, true);
});
}
}
}
});
if(KEY.isVerticalMovement(key) && ctrl.items.length > 0){
_ensureHighlightVisible();
}
if (key === KEY.ENTER || key === KEY.ESC) {
e.preventDefault();
e.stopPropagation();
}
});
). I'm not sure it can be fixed to the local digest cycle. The ui-select2 library is wiser on filtering, it does not triggers the digest cycle on the root scope and faster on filtering, but deprecated 2 years ago.

@yogeshgadge
Copy link

I am going with a pagination support that works on scroll. It could be the raw list or the filtered list which may also be bad.

Plnkr
Detailed solution on stackoverflow

@mohamadnajiya
Copy link

mohamadnajiya commented Jun 2, 2017

@yogeshgadge add clear to multiple ui-select will stop populating the dropdown

 $scope.clear = function($event) {
      vm.multipleDemo.selectedPeople=undefined;

  };

Plunk below

Plnkr

Any idea how to fix that?

# for free to subscribe to this conversation on GitHub. Already have an account? #.
Projects
None yet
Development

No branches or pull requests