Recently I’ve discovered that XtraVerticalGrid, a nice vertical grid from [DevEx], has some serious problems with speed when doing batch updates. Usually you should enclose batch updates within BeginUpdate/EndUpdate method calls. This usually prevents processing/redrawing within the control when one does many updates to underlying datasource at once. The neat effect of BeginUpdate/EndUpdate results in dramatic speed improvements.
However, XtraVerticalGrid doesn’t implement batch BeginUpdate/EndUpdate very well and still massively processes the changes even though developer doesn’t want to. Basically an operation that should take a fraction of second took more than 3s, which is an annoyance to the user, due to this problem.
Here is the workaround
Derive a class, i.e. RhVerticalGrid from VGridControl and add this piece of code:
public class RhVerticalGrid: VGridControl { private int lockUpdateCount; #region BeginUpdate public override void BeginUpdate() { lockUpdateCount++; base.BeginUpdate(); } #endregion #region EndUpdate public override void EndUpdate() { lockUpdateCount--; Debug.Assert(lockUpdateCount >= 0); base.EndUpdate(); } #endregion #region CancelUpdate public override void CancelUpdate() { lockUpdateCount--; Debug.Assert(lockUpdateCount >= 0); base.CancelUpdate(); } #endregion protected override void OnDataManager_ListChanged(object sender, ListChangedEventArgs e) { if (lockUpdateCount == 0) base.OnDataManager_ListChanged(sender, e); } public override void InvalidateRecord(int recordIndex) { if (lockUpdateCount == 0) base.InvalidateRecord(recordIndex); } }
That’s it. My execution speed dropped down from >3s to almost instantaneous execution. Begin|End|CancellUpdate methods just increment/decrement lock counter (when lockUpdateCount == 0 the updates are allowed, otherwise not). The main improvements are within OnDataManager_ListChanged and InvalidateRecod methods where I propagate the processing only if updates are allowed. That’s it – use the derived grid control instead of the original. Simple as that. And make sure your batch updates are enclosed with Begin|EndUpdate methods!
How does one find such culprits?
If you are scratching your head with the question “how does one find the culprit of such slowdowns”? The answer lies in performance profiling. To find this one I’ve used my favorite AQTime profiler (much more than just a performance profiler) and quickly found the culprit. I should also mention that this isn’t the first time that AQTime helped me to find both memory and performance problems. Yep, a performance and memory profiler is a must have tool for serious developer, even better if this is AQTime. Anyway, here is clear picture (from AQTime graph view) of the culprit in action:
BTW, here is the link to the bug report on the [DevEx] support center I made today.