High Performance
                          Tabular Databinding


                                     Tony Juckel
                              Cargill Risk Management


Tuesday, April 19, 2011
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
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
Pieces	
  of	
  the	
  Puzzle




                                          Table	
  or	
  Tree	
  Viewer
                                        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


Tuesday, April 19, 2011
Pieces	
  of	
  the	
  Puzzle




                                                  Table	
  or	
  Tree	
  Viewer
            ObservableListContentProvider
                                                ID              Price               Delta
                    Domain	
  Object	
  1   Obj	
  1	
  ID   Obj	
  1	
  Price   Obj	
  1	
  Delta

                    Domain	
  Object	
  2   Obj	
  2	
  ID   Obj	
  2	
  Price   Obj	
  2	
  Delta

                    Domain	
  Object	
  3   Obj	
  3	
  ID   Obj	
  3	
  Price   Obj	
  3	
  Delta


Tuesday, April 19, 2011
Pieces	
  of	
  the	
  Puzzle

                          ID	
  ObservableMap

                    Price	
  ObservableMap

                    Delta	
  ObservableMap




                                                      Table	
  or	
  Tree	
  Viewer
            ObservableListContentProvider
                                                    ID              Price               Delta
                    Domain	
  Object	
  1       Obj	
  1	
  ID   Obj	
  1	
  Price   Obj	
  1	
  Delta

                    Domain	
  Object	
  2       Obj	
  2	
  ID   Obj	
  2	
  Price   Obj	
  2	
  Delta

                    Domain	
  Object	
  3       Obj	
  3	
  ID   Obj	
  3	
  Price   Obj	
  3	
  Delta


Tuesday, April 19, 2011
Pieces	
  of	
  the	
  Puzzle

                          ID	
  ObservableMap      ID	
  ObservableMapCellLabelProvider

                    Price	
  ObservableMap      Price	
  ObservableMapCellLabelProvider

                    Delta	
  ObservableMap      Delta	
  ObservableMapCellLabelProvider




                                                              Table	
  or	
  Tree	
  Viewer
            ObservableListContentProvider
                                                            ID              Price               Delta
                    Domain	
  Object	
  1               Obj	
  1	
  ID   Obj	
  1	
  Price   Obj	
  1	
  Delta

                    Domain	
  Object	
  2               Obj	
  2	
  ID   Obj	
  2	
  Price   Obj	
  2	
  Delta

                    Domain	
  Object	
  3               Obj	
  3	
  ID   Obj	
  3	
  Price   Obj	
  3	
  Delta


Tuesday, April 19, 2011
Pieces	
  of	
  the	
  Puzzle

                           ID	
  ObservableMap                   ID	
  ObservableMapCellLabelProvider

                    Price	
  ObservableMap                    Price	
  ObservableMapCellLabelProvider

                    Delta	
  ObservableMap                    Delta	
  ObservableMapCellLabelProvider


                  1)	
  Domain	
  Object	
  1	
  update	
  
                  notifies	
  listening	
  
                  ObservableMaps.




                                                                            Table	
  or	
  Tree	
  Viewer
            ObservableListContentProvider
                                                                          ID              Price               Delta
                    Domain	
  Object	
  1                             Obj	
  1	
  ID   Obj	
  1	
  Price   Obj	
  1	
  Delta

                    Domain	
  Object	
  2                             Obj	
  2	
  ID   Obj	
  2	
  Price   Obj	
  2	
  Delta

                    Domain	
  Object	
  3                             Obj	
  3	
  ID   Obj	
  3	
  Price   Obj	
  3	
  Delta


Tuesday, April 19, 2011
Pieces	
  of	
  the	
  Puzzle
                  2)	
  ObservableMaps	
  notify	
  
                  their	
  label	
  providers.




                          ID	
  ObservableMap             ID	
  ObservableMapCellLabelProvider

                    Price	
  ObservableMap             Price	
  ObservableMapCellLabelProvider

                    Delta	
  ObservableMap             Delta	
  ObservableMapCellLabelProvider




                                                                     Table	
  or	
  Tree	
  Viewer
            ObservableListContentProvider
                                                                   ID              Price               Delta
                    Domain	
  Object	
  1                      Obj	
  1	
  ID   Obj	
  1	
  Price   Obj	
  1	
  Delta

                    Domain	
  Object	
  2                      Obj	
  2	
  ID   Obj	
  2	
  Price   Obj	
  2	
  Delta

                    Domain	
  Object	
  3                      Obj	
  3	
  ID   Obj	
  3	
  Price   Obj	
  3	
  Delta


Tuesday, April 19, 2011
Pieces	
  of	
  the	
  Puzzle

                          ID	
  ObservableMap            ID	
  ObservableMapCellLabelProvider

                    Price	
  ObservableMap        Price	
  ObservableMapCellLabelProvider

                    Delta	
  ObservableMap        Delta	
  ObservableMapCellLabelProvider


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




                                                                          Table	
  or	
  Tree	
  Viewer
            ObservableListContentProvider
                                                                        ID                 Price                  Delta
                    Domain	
  Object	
  1                          Obj	
  1	
  ID      Obj	
  1	
  Price      Obj	
  1	
  Delta

                    Domain	
  Object	
  2                          Obj	
  2	
  ID      Obj	
  2	
  Price      Obj	
  2	
  Delta

                    Domain	
  Object	
  3                          Obj	
  3	
  ID      Obj	
  3	
  Price      Obj	
  3	
  Delta


Tuesday, April 19, 2011
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
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
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
Digging Deeper


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




Tuesday, April 19, 2011
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
Choices in
                             ObservableMaps

                     • M1: Each map traverses subproperty
                     • M2: Share an intermediate ObservableMap
                          and use observeDetail for property
                          changes




Tuesday, April 19, 2011
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
Numbers!
    Case N(1|2)/M1:                1000 Content Elements
    Notifying on greeks     Initial Bind (ms) Update (ms)
    property updates,                      510            9270
    and each map doing
                                  10,000 Content Elements
    property traversal
                            Initial Bind (ms) Update (ms)
                                          4325     10+ minutes




Tuesday, April 19, 2011
Numbers!
    Case N(3)/M1:                  1000 Content Elements
    Notifying that greeks   Initial Bind (ms) Update (ms)
    object changed, and                    510          13134
    each map doing
                                  10,000 Content Elements
    property traversal.
                            Initial Bind (ms) Update (ms)
                                          4325     10+ minutes




Tuesday, April 19, 2011
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
Profiling Results
                                                      getterCalled()
                               N1/M1                              93071
                               N3/M1                              93467

                          •   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)



Tuesday, April 19, 2011
With Intermediate Map
     Case N(1|2)/M2:                 1000 Content Elements
     Notifying on greeks      Initial Bind (ms) Update (ms)
     property updates,                       468            8454
     and using
                                    10,000 Content Elements
     intermediate greeks
                              Initial Bind (ms) Update (ms)
     map. Better, but still
                                            3852     10+ minutes
     far from usable.



Tuesday, April 19, 2011
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
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
Without Leaf Listening
                                   1000 Content Elements
                            Initial Bind (ms) Update (ms)
     Case N3/M3:                           262              10
     Only listens for
     changes to                   10,000 Content Elements
     Instrument.greeks      Initial Bind (ms) Update (ms)
                                          2263              89




Tuesday, April 19, 2011
Profiling Results
                                                       getterCalled()
                               N1/M1                                93071
                               N1/M2                                93467
                               N3/M3                                  269



                          •   Dramatic reduction in calls to
                              ObservableTracker#getterCalled()

                          •   Horrible class name, but finally gives acceptable
                              performance




Tuesday, April 19, 2011
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
Questions?

                     • ajuckel@gmail.com
                     • https://github.com/ajuckel/
                          org.example.emfdb
                     • @ajuckel
                     • http://sputteringdigitized.blogspot.com

Tuesday, April 19, 2011

High Performance Tabular Databinding

  • 1.
    High Performance Tabular Databinding Tony Juckel Cargill Risk Management Tuesday, April 19, 2011
  • 2.
    What Are WeGoing 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
  • 3.
    Who Am IAnd 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
  • 4.
    Pieces  of  the  Puzzle Table  or  Tree  Viewer 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 Tuesday, April 19, 2011
  • 5.
    Pieces  of  the  Puzzle Table  or  Tree  Viewer ObservableListContentProvider ID Price Delta Domain  Object  1 Obj  1  ID Obj  1  Price Obj  1  Delta Domain  Object  2 Obj  2  ID Obj  2  Price Obj  2  Delta Domain  Object  3 Obj  3  ID Obj  3  Price Obj  3  Delta Tuesday, April 19, 2011
  • 6.
    Pieces  of  the  Puzzle ID  ObservableMap Price  ObservableMap Delta  ObservableMap Table  or  Tree  Viewer ObservableListContentProvider ID Price Delta Domain  Object  1 Obj  1  ID Obj  1  Price Obj  1  Delta Domain  Object  2 Obj  2  ID Obj  2  Price Obj  2  Delta Domain  Object  3 Obj  3  ID Obj  3  Price Obj  3  Delta Tuesday, April 19, 2011
  • 7.
    Pieces  of  the  Puzzle ID  ObservableMap ID  ObservableMapCellLabelProvider Price  ObservableMap Price  ObservableMapCellLabelProvider Delta  ObservableMap Delta  ObservableMapCellLabelProvider Table  or  Tree  Viewer ObservableListContentProvider ID Price Delta Domain  Object  1 Obj  1  ID Obj  1  Price Obj  1  Delta Domain  Object  2 Obj  2  ID Obj  2  Price Obj  2  Delta Domain  Object  3 Obj  3  ID Obj  3  Price Obj  3  Delta Tuesday, April 19, 2011
  • 8.
    Pieces  of  the  Puzzle ID  ObservableMap ID  ObservableMapCellLabelProvider Price  ObservableMap Price  ObservableMapCellLabelProvider Delta  ObservableMap Delta  ObservableMapCellLabelProvider 1)  Domain  Object  1  update   notifies  listening   ObservableMaps. Table  or  Tree  Viewer ObservableListContentProvider ID Price Delta Domain  Object  1 Obj  1  ID Obj  1  Price Obj  1  Delta Domain  Object  2 Obj  2  ID Obj  2  Price Obj  2  Delta Domain  Object  3 Obj  3  ID Obj  3  Price Obj  3  Delta Tuesday, April 19, 2011
  • 9.
    Pieces  of  the  Puzzle 2)  ObservableMaps  notify   their  label  providers. ID  ObservableMap ID  ObservableMapCellLabelProvider Price  ObservableMap Price  ObservableMapCellLabelProvider Delta  ObservableMap Delta  ObservableMapCellLabelProvider Table  or  Tree  Viewer ObservableListContentProvider ID Price Delta Domain  Object  1 Obj  1  ID Obj  1  Price Obj  1  Delta Domain  Object  2 Obj  2  ID Obj  2  Price Obj  2  Delta Domain  Object  3 Obj  3  ID Obj  3  Price Obj  3  Delta Tuesday, April 19, 2011
  • 10.
    Pieces  of  the  Puzzle ID  ObservableMap ID  ObservableMapCellLabelProvider Price  ObservableMap Price  ObservableMapCellLabelProvider Delta  ObservableMap Delta  ObservableMapCellLabelProvider 3)  Label  providers  notify  the  table  that  their  label   has  changed  for  a  given  content  item. Table  or  Tree  Viewer ObservableListContentProvider ID Price Delta Domain  Object  1 Obj  1  ID Obj  1  Price Obj  1  Delta Domain  Object  2 Obj  2  ID Obj  2  Price Obj  2  Delta Domain  Object  3 Obj  3  ID Obj  3  Price Obj  3  Delta Tuesday, April 19, 2011
  • 11.
    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
  • 12.
    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
  • 13.
    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
  • 14.
    Digging Deeper • Sample Application • https://github.com/ajuckel/ org.example.emfdb Tuesday, April 19, 2011
  • 15.
    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
  • 16.
    Choices in ObservableMaps • M1: Each map traverses subproperty • M2: Share an intermediate ObservableMap and use observeDetail for property changes Tuesday, April 19, 2011
  • 17.
    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
  • 18.
    Numbers! Case N(1|2)/M1: 1000 Content Elements Notifying on greeks Initial Bind (ms) Update (ms) property updates, 510 9270 and each map doing 10,000 Content Elements property traversal Initial Bind (ms) Update (ms) 4325 10+ minutes Tuesday, April 19, 2011
  • 19.
    Numbers! Case N(3)/M1: 1000 Content Elements Notifying that greeks Initial Bind (ms) Update (ms) object changed, and 510 13134 each map doing 10,000 Content Elements property traversal. Initial Bind (ms) Update (ms) 4325 10+ minutes Tuesday, April 19, 2011
  • 20.
    Where Has theTime 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
  • 21.
    Profiling Results getterCalled() N1/M1 93071 N3/M1 93467 • 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) Tuesday, April 19, 2011
  • 22.
    With Intermediate Map Case N(1|2)/M2: 1000 Content Elements Notifying on greeks Initial Bind (ms) Update (ms) property updates, 468 8454 and using 10,000 Content Elements intermediate greeks Initial Bind (ms) Update (ms) map. Better, but still 3852 10+ minutes far from usable. Tuesday, April 19, 2011
  • 23.
    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
  • 24.
    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
  • 25.
    Without Leaf Listening 1000 Content Elements Initial Bind (ms) Update (ms) Case N3/M3: 262 10 Only listens for changes to 10,000 Content Elements Instrument.greeks Initial Bind (ms) Update (ms) 2263 89 Tuesday, April 19, 2011
  • 26.
    Profiling Results getterCalled() N1/M1 93071 N1/M2 93467 N3/M3 269 • Dramatic reduction in calls to ObservableTracker#getterCalled() • Horrible class name, but finally gives acceptable performance Tuesday, April 19, 2011
  • 27.
    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
  • 28.
    Questions? • ajuckel@gmail.com • https://github.com/ajuckel/ org.example.emfdb • @ajuckel • http://sputteringdigitized.blogspot.com Tuesday, April 19, 2011