Serious performance issues with BindingList<T>.InsertItem() in BLB

Serious performance issues with BindingList<T>.InsertItem() in BLB

Old forum URL: forums.lhotka.net/forums/t/7711.aspx


Michael posted on Thursday, October 01, 2009

Hi everyone

We are developing an AutoCAD plugin, which must respond to copy and paste commands. This can mean creating several hundred new copies of existing business objects and adding them to the BLB within the root BB.

While testing this, I discovered that performance degrades alarmingly as the number of objects to copy increases, with each subsequent insert taking a bit longer than the previous. I have narrowed it down to the call to BindingList<T>.InsertItem(index, item), so I was glad it wasn't CSLA, but disappointed that I may not be able to do anything about it.

The BLB is not bound to anything during this process. The first insert takes around 15ms, the 100th 450ms, and the 400th well over 2s. This means copying 100 objects is taking around 23s, while 400 takes over six minutes. I would hate to be the draftsman who has to copy and paste 1000 objects. After saving the BB, the times start at 15ms again, but saving isn't always practical.

Is there anything I can do to improve this?

Kind regards
Michael

JonnyBee replied on Thursday, October 01, 2009

Hi,
 
Are you really sure that databinding is not active?

Are you inserting items at position 0 or appending to list?

My suggestion would be to build a list of new items (simply a List<T>) and then add new items in one call (AddRange)  rather than adding each separate item.


Michael replied on Thursday, October 01, 2009

Hi Jonny

Thanks for the reply.

Objects within the BB are bound while dialogs are shown, and unbound when the screens are closed. The code in question responds to AutoCAD's copy and paste event, so there's no screens involved, and definitely no binding.

I'm calling the usual BLB.Add(item).

AddRange is a good suggestion. I'll try it tomorrow and report my findings.

Thanks again
Michael

ajj3085 replied on Thursday, October 01, 2009

Also, I would try setting RaiseListChangedEvents to false, just to be sure something isn't listening to events as each item goes into the list.

Michael replied on Thursday, October 01, 2009

This doesn't really make sense to me, but when I use AddRange (with RaiseListChangedEvents on), the performance is much worse. Instead of each subsequent insert taking a bit longer (going from 15ms for the first insert to 450ms for the 100th), the total time equates to 450ms each, i.e. double the time.

AddRange is implemented as:

foreach (var element in range)
    this.Add(element);


Maybe the compiled code is "optimised" to allocate space in the array for the number of elements in the range being added.

The answer is to switch off list changed events, thanks Andy (I should have thought of that!). The BLB does not have to be bound for these events to affect performance, which is why we switch them off in Child_Fetch, well before any binding happens.

Regards
Michael

Copyright (c) Marimer LLC