28
High Performance Tabular Databinding Tony Juckel Cargill Risk Management Tuesday, April 19, 2011

High Performance Tabular Databinding

  • Upload
    ajuckel

  • View
    920

  • Download
    1

Embed Size (px)

Citation preview

Page 1: High Performance Tabular Databinding

High Performance Tabular Databinding

Tony JuckelCargill Risk Management

Tuesday, April 19, 2011

Page 2: High Performance Tabular Databinding

What Are We Going to Cover

• Quick overview of the databinding API

• Some performance numbers

• Tips on getting the best performance with the current iteration of the databinding framework

Tuesday, April 19, 2011

Page 3: High Performance Tabular Databinding

Who Am I And Why Do I Care?

• Building trading applications on top of Eclipse for Cargill Risk Management

• Want to display a high volume of very volatile data

• Appreciate the Databinding APIs for ancillary benefits (table editors, viewer comparators, etc)

Tuesday, April 19, 2011

Page 4: High Performance Tabular Databinding

ID Price Delta

Obj  1  ID Obj  1  Price Obj  1  Delta

Obj  2  ID Obj  2  Price Obj  2  Delta

Obj  3  ID Obj  3  Price Obj  3  Delta

Table  or  Tree  Viewer

Pieces  of  the  Puzzle

Tuesday, April 19, 2011

Page 5: High Performance Tabular Databinding

Pieces  of  the  Puzzle

ObservableListContentProvider

Domain  Object  1

Domain  Object  2

Domain  Object  3

ID Price Delta

Obj  1  ID Obj  1  Price Obj  1  Delta

Obj  2  ID Obj  2  Price Obj  2  Delta

Obj  3  ID Obj  3  Price Obj  3  Delta

Table  or  Tree  Viewer

Tuesday, April 19, 2011

Page 6: High Performance Tabular Databinding

Pieces  of  the  Puzzle

ObservableListContentProvider

ID  ObservableMap

Delta  ObservableMap

Price  ObservableMap

ID Price Delta

Obj  1  ID Obj  1  Price Obj  1  Delta

Obj  2  ID Obj  2  Price Obj  2  Delta

Obj  3  ID Obj  3  Price Obj  3  Delta

Table  or  Tree  Viewer

Domain  Object  1

Domain  Object  2

Domain  Object  3

Tuesday, April 19, 2011

Page 7: High Performance Tabular Databinding

Pieces  of  the  Puzzle

ObservableListContentProvider

ID  ObservableMap

Delta  ObservableMap

Price  ObservableMap

ID  ObservableMapCellLabelProvider

Delta  ObservableMapCellLabelProvider

Price  ObservableMapCellLabelProvider

ID Price Delta

Obj  1  ID Obj  1  Price Obj  1  Delta

Obj  2  ID Obj  2  Price Obj  2  Delta

Obj  3  ID Obj  3  Price Obj  3  Delta

Table  or  Tree  Viewer

Domain  Object  1

Domain  Object  2

Domain  Object  3

Tuesday, April 19, 2011

Page 8: High Performance Tabular Databinding

Pieces  of  the  Puzzle

ObservableListContentProvider

ID  ObservableMap

Delta  ObservableMap

Price  ObservableMap

ID  ObservableMapCellLabelProvider

Delta  ObservableMapCellLabelProvider

Price  ObservableMapCellLabelProvider

1)  Domain  Object  1  update  notifies  listening  ObservableMaps.

ID Price Delta

Obj  1  ID Obj  1  Price Obj  1  Delta

Obj  2  ID Obj  2  Price Obj  2  Delta

Obj  3  ID Obj  3  Price Obj  3  Delta

Table  or  Tree  Viewer

Domain  Object  1

Domain  Object  2

Domain  Object  3

Tuesday, April 19, 2011

Page 9: High Performance Tabular Databinding

Pieces  of  the  Puzzle

ObservableListContentProvider

ID  ObservableMap

Delta  ObservableMap

Price  ObservableMap

ID  ObservableMapCellLabelProvider

Delta  ObservableMapCellLabelProvider

Price  ObservableMapCellLabelProvider

2)  ObservableMaps  notify  their  label  providers.

ID Price Delta

Obj  1  ID Obj  1  Price Obj  1  Delta

Obj  2  ID Obj  2  Price Obj  2  Delta

Obj  3  ID Obj  3  Price Obj  3  Delta

Table  or  Tree  Viewer

Domain  Object  1

Domain  Object  2

Domain  Object  3

Tuesday, April 19, 2011

Page 10: High Performance Tabular Databinding

Pieces  of  the  Puzzle

ObservableListContentProvider

ID  ObservableMap

Delta  ObservableMap

Price  ObservableMap

ID  ObservableMapCellLabelProvider

Delta  ObservableMapCellLabelProvider

Price  ObservableMapCellLabelProvider

3)  Label  providers  notify  the  table  that  their  label  has  changed  for  a  given  content  item.

ID Price Delta

Obj  1  ID Obj  1  Price Obj  1  Delta

Obj  2  ID Obj  2  Price Obj  2  Delta

Obj  3  ID Obj  3  Price Obj  3  Delta

Table  or  Tree  Viewer

Domain  Object  1

Domain  Object  2

Domain  Object  3

Tuesday, April 19, 2011

Page 11: High Performance Tabular Databinding

Easy Performance Boosts

• SWT.VIRTUAL to speed initial table creation

• Improves initial bind even without an ILazyContentProvider

• Don’t overmutate bound state

Tuesday, April 19, 2011

Page 12: High Performance Tabular Databinding

Easy Performance Boosts

• StructuredViewer#setUseHashlookup

• Helps table efficiently find Widgets associated with an updated Content Item

• If false, we notice performance degredation at just 200 Content Items

Tuesday, April 19, 2011

Page 13: High Performance Tabular Databinding

Bug #303847

• Only affects Properties API

• MapSimpleValueObservableMap

• AbstractMap#get, #containsKey, etc

• Fixed in 3.6

• Feature patched in our app (still on 3.5)

Tuesday, April 19, 2011

Page 14: High Performance Tabular Databinding

Digging Deeper

• Sample Application

• https://github.com/ajuckel/org.example.emfdb

Tuesday, April 19, 2011

Page 15: High Performance Tabular Databinding

Choices in Notification

• Firing Changes

• N1: Notify about each property change individually

• N2: Notify about each property change in batch (via NotificationChain)

• N3: Notify that INSTRUMENT__GREEKS has changed

Tuesday, April 19, 2011

Page 16: High Performance Tabular Databinding

Choices in ObservableMaps

• M1: Each map traverses subproperty

• M2: Share an intermediate ObservableMap and use observeDetail for property changes

Tuesday, April 19, 2011

Page 17: High Performance Tabular Databinding

Metrics

• Initial Bind Performance

• How long does it take to initially populate the table?

• Update a subset of data

• How long to update greeks for ~10% of content items?

Tuesday, April 19, 2011

Page 18: High Performance Tabular Databinding

Numbers!

1000 Content Elements1000 Content ElementsInitial Bind (ms) Update (ms)

510 9270

10,000 Content Elements10,000 Content ElementsInitial Bind (ms) Update (ms)

4325 10+ minutes

Case N(1|2)/M1:Notifying on greeks property updates, and each map doing property traversal

Tuesday, April 19, 2011

Page 19: High Performance Tabular Databinding

Numbers!

1000 Content Elements1000 Content ElementsInitial Bind (ms) Update (ms)

510 13134

10,000 Content Elements10,000 Content ElementsInitial Bind (ms) Update (ms)

4325 10+ minutes

Case N(3)/M1:Notifying that greeks object changed, and each map doing property traversal.

Tuesday, April 19, 2011

Page 20: High Performance Tabular Databinding

Where Has the Time Gone?

• Used VisualVM to collect profiling data

• VisualVM profiling has a very high probe effect, so profiled much smaller bind (only 100 content elements)

• Holy ObservableTracker.getterCalled(), Batman!

Tuesday, April 19, 2011

Page 21: High Performance Tabular Databinding

Profiling Results

• Number of times getterCalled() was called when updating 6 properties on each of 14 content elements from a set of 100

• Calls scale with size of ObservableSet, not number of changed elements

• (+ (* 8400 8) (* 8484 3) 166 84 2 84 83)

getterCalled()N1/M1N3/M1

9307193467

Tuesday, April 19, 2011

Page 22: High Performance Tabular Databinding

With Intermediate Map

1000 Content Elements1000 Content ElementsInitial Bind (ms) Update (ms)

468 8454

10,000 Content Elements10,000 Content ElementsInitial Bind (ms) Update (ms)

3852 10+ minutes

Case N(1|2)/M2:Notifying on greeks property updates, and using intermediate greeks map. Better, but still far from usable.

Tuesday, April 19, 2011

Page 23: High Performance Tabular Databinding

What’s Next?

• We’ve found that traversing properties via IObservables is VERY expensive, due to the usage of ObservableTracker.getterCalled()

• Can we create an IObservableMap that only listens to part of the property chain, yet still allows getting/setting of leaf values?

Tuesday, April 19, 2011

Page 24: High Performance Tabular Databinding

Yes We Can

• EMFPartialListeningMapDecorator

• Uses an intermediate ObservableMap as a delegate for all property listening.

• Uses IValueProperty#getValue(Object) and IValueProperty#setValue(Object,Object) to get/set leaf values without ObservableTracker.getterCalled()

Tuesday, April 19, 2011

Page 25: High Performance Tabular Databinding

Without Leaf Listening

1000 Content Elements1000 Content ElementsInitial Bind (ms) Update (ms)

262 10

10,000 Content Elements10,000 Content ElementsInitial Bind (ms) Update (ms)

2263 89

Case N3/M3:Only listens for changes to Instrument.greeks

Tuesday, April 19, 2011

Page 26: High Performance Tabular Databinding

Profiling Results

• Dramatic reduction in calls to ObservableTracker#getterCalled()

• Horrible class name, but finally gives acceptable performance

getterCalled()N1/M1N1/M2N3/M3

9307193467

269

Tuesday, April 19, 2011

Page 27: High Performance Tabular Databinding

In Conclusion

• Use SWT.VIRTUAL

• Use StructuredViewer#setUseHashlookup()

• Don’t use observables directly on properties of properties.

• Either project values of interest into your content item, or use something like EMFPartialListeningMapDecorator

Tuesday, April 19, 2011