MVC Performance, Ember.js
-
Upload
standa-opichal -
Category
Technology
-
view
1.400 -
download
1
description
Transcript of MVC Performance, Ember.js
MVC Performance Ember.js
Standa Opichal@opichals
MVC
Server Client
ViewControllerModel HTML
Single Page App MVC
Server Client
VCM HTMLVCM ?
SPA Load Performance
VCM HTML?
JS
VCM
ClientServer
Client MVC Performance
ViewControllerModel
Runtime PerformanceExpressiveness (Clarity + Brevity)Performance Conscious Concepts
Framework Performance
Instance ConstructionEventingKey-Value Observing
Runtime Performance
ViewControllerModel
JavaScript
var brendan = { name: ‘Brendan’};
Performance: very fastKVO: not really
Construction
Object
var eric = new Y.Base({ name: ‘Eric’})
var tom = Ember.Object.create({ name: ‘Tom’})
Construction: KVO
KVO
var tom = Ember.Object.create({ name: ‘Tom’
_nameDidChange: function() { }.observes(‘name’)
firstName: function() { }.property(‘name’)})
Construction: KVO
KVO
for (var i=0; i<10000; i++) {constructSingleKVO();
}
SynchronousBlocks browser event loop till finishedIs it fast enough?
Construction Performance
KVO
Expected Construction PerformanceTime
Loop
cou
nt
Expectation
KVO
Construction Performance WTFTime
Loop
cou
nt
RealitySynchronous for loop!? WTF?
GCView
ControllerModel
Lifecycle EventsInitializingDestroying
KVO Book KeepingObservers
Varies significantly with JSVM, Browser, OS
Construction Performance Summary
ViewControllerModel
Eventing
Barebone eventing in YUI vs Ember.js
Eventing: YUI
kvo.fire(‘export’, { report: item })
kvo.on(‘export’, function onExport(e) {e.report.focus(); // facadee.preventDefault(); // DOM-likee.stop();
});kvo.after(‘export’, function afterExport(e) {
e.report.loseFocus();});
Eventing: Ember.js
controller.send(‘export’, { report: item })
// route actionexport: function onExport(args) {
args.report.focus(); // facade}
Eventing Performance
Facading, DOM-like events, default actions-> Lots of throwaway instances
-> frequent GC events
Simple method calls win!
YUIkeyChange DOM-like Events
Ember.jsDeclarative Observer NotationEventing is not used
KVO
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
Ember.js wins
Observers do by design way lesswork to function
+ Declarative is also readable
KVO Performance
ExpressivenessTemplatesLive BindingsDependency Injection
Ember.js ExpressivenessApp.UserController = Ember.ObjectController.extend({
content: Em.Object.create({name: ‘Tom’
});firstNameBinding: ‘content.name’
});
user-template:User: {{firstName}}
Performance Conscious Design
On-DemandAsync
Ember.js wins
Observers do by design way lesswork to function
+ Declarative is also readable
Example: GoodData Dashboard
Server Data
var tab = { items: [ // items.length ~ 100
{ type: ‘filter’ },{ type: ‘report’ },{ type: ‘line’ },...
]}
Dashboard Model
Tab = Em.Object.extend({ // KVOitems: Array<TabItem>
})
TabItem = Em.Object.extend({type: ...
})
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
// Want no TabItem instances created at firstvar tab = Tab.create({tabData: tabData});
// On-demand TabItem creationtab.get(‘items’);
Lazy Materialization FTW
Tab = Em.Object.extend({tabData: {...}items: function() {
return this.get(‘tabData’).items.map(function(item) {return TabItem.create(item);
})}.property(‘tabData’),
})
Lazy Materialization
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?
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 declarativethis.addObserver(‘items’, this._itemsDidChange);
}});
Ugly on-demand addObserver
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
Use of Object.observe()Would make observing asyncCurrent Chrome CanaryIn Ember 2.0 (?)
Performance Future
Thank You!