MVC Performance, Ember.js

1,750 views

Published on

About how a core runtime and overall principles design influences the frontend framework performance.

Comparison examples from Ember.js and YUI3

Published in: Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,750
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
30
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

MVC Performance, Ember.js

  1. 1. MVC Performance Ember.js Standa Opichal @opichals
  2. 2. MVC Server Client ViewControllerModel HTML
  3. 3. Single Page App MVC Server Client VCM HTMLVCM ?
  4. 4. SPA Load Performance VCM HTML? JS VCM ClientServer
  5. 5. Client MVC Performance ViewControllerModel
  6. 6. Runtime Performance Expressiveness (Clarity + Brevity) Performance Conscious Concepts Framework Performance
  7. 7. Instance Construction Eventing Key-Value Observing Runtime Performance View Controller Model
  8. 8. JavaScript var brendan = { name: ‘Brendan’ }; Performance: very fast KVO: not really Construction Object
  9. 9. var eric = new Y.Base({ name: ‘Eric’ }) var tom = Ember.Object.create({ name: ‘Tom’ }) Construction: KVO KVO
  10. 10. var tom = Ember.Object.create({ name: ‘Tom’ _nameDidChange: function() { }.observes(‘name’) firstName: function() { }.property(‘name’) }) Construction: KVO KVO
  11. 11. for (var i=0; i<10000; i++) { constructSingleKVO(); } Synchronous Blocks browser event loop till finished Is it fast enough? Construction Performance KVO
  12. 12. Expected Construction Performance Time Loopcount Expectation KVO
  13. 13. Construction Performance WTF Time Loopcount Reality Synchronous for loop!? WTF? GC View Controller Model
  14. 14. Lifecycle Events Initializing Destroying KVO Book Keeping Observers Varies significantly with JSVM, Browser, OS Construction Performance Summary View Controller Model
  15. 15. Eventing Barebone eventing in YUI vs Ember.js
  16. 16. Eventing: YUI kvo.fire(‘export’, { report: item }) kvo.on(‘export’, function onExport(e) { e.report.focus(); // facade e.preventDefault(); // DOM-like e.stop(); }); kvo.after(‘export’, function afterExport(e) { e.report.loseFocus(); });
  17. 17. Eventing: Ember.js controller.send(‘export’, { report: item }) // route action export: function onExport(args) { args.report.focus(); // facade }
  18. 18. Eventing Performance Facading, DOM-like events, default actions -> Lots of throwaway instances -> frequent GC events Simple method calls win!
  19. 19. YUI keyChange DOM-like Events Ember.js Declarative Observer Notation Eventing is not used KVO
  20. 20. Ember.Object.create({ name: ‘Tom’, content: Em.Object.create({ name: ‘Jerry’ }), nameDidChange: function() { // this runs upon name change }.observes(‘name’, ‘content.name’) }); Ember.js Observers
  21. 21. Ember.js wins Observers do by design way less work to function + Declarative is also readable KVO Performance
  22. 22. Expressiveness Templates Live Bindings Dependency Injection
  23. 23. Ember.js Expressiveness App.UserController = Ember.ObjectController.extend({ content: Em.Object.create({ name: ‘Tom’ }); firstNameBinding: ‘content.name’ }); user-template: User: {{firstName}}
  24. 24. Performance Conscious Design On-Demand Async
  25. 25. Ember.js wins Observers do by design way less work to function + Declarative is also readable Example: GoodData Dashboard
  26. 26. Server Data var tab = { items: [ // items.length ~ 100 { type: ‘filter’ }, { type: ‘report’ }, { type: ‘line’ }, ... ] }
  27. 27. Dashboard Model Tab = Em.Object.extend({ // KVO items: Array<TabItem> }) TabItem = Em.Object.extend({ type: ... })
  28. 28. Materialization Server Data -> Model Instances var tab = Tab.create(tabData) var items = tab.get(‘items’); tabData.items.forEach(function(item) { items.push(TabItem.create(item)) }) Slow: Dashboard ~ 10 Tabs * 100 items
  29. 29. // Want no TabItem instances created at first var tab = Tab.create({tabData: tabData}); // On-demand TabItem creation tab.get(‘items’); Lazy Materialization FTW
  30. 30. Tab = Em.Object.extend({ tabData: {...} items: function() { return this.get(‘tabData’).items.map(function(item) { return TabItem.create(item); }) }.property(‘tabData’), }) Lazy Materialization
  31. 31. Tab = Em.Object.extend({ tabData: {...} items: function() { ... }.property(‘tabData’), _itemsDidChange: function() { var types = this.get(‘items’).filter(...); // does stuff every items/tabData change }.observes(‘items’); // gets ‘items’ on Tab creation }) Does it work?
  32. 32. Tab = Em.Object.extend({ tabData: {...} items: function() { … }.property(‘tabData’), init: function () { set(‘tabData’, {}); // not declarative, unclear why, ugly // -> sooner or later somebody // _will_ forget and refactor to declarative this.addObserver(‘items’, this._itemsDidChange); } }); Ugly on-demand addObserver
  33. 33. Tab = Em.Object.extend({ items: function() { … }.property(‘tabData’), _itemsDidChange: function() { var types = this.get(‘items’).filter(...); }.observes(‘items’); }); Observers are initialized after the ‘items’ computed property materialization (a tab.get(‘items’) call) Since Ember.js 1.0-rc8
  34. 34. Use of Object.observe() Would make observing async Current Chrome Canary In Ember 2.0 (?) Performance Future
  35. 35. Thank You!

×