Skip to content

Instantly share code, notes, and snippets.

@jelhan
Last active June 27, 2018 15:30
Show Gist options
  • Save jelhan/c9a514bc4a8670d1d4685c97f56f0ea4 to your computer and use it in GitHub Desktop.
Save jelhan/c9a514bc4a8670d1d4685c97f56f0ea4 to your computer and use it in GitHub Desktop.
sort-macro-performance
import Ember from 'ember';
export default Ember.Controller.extend({
appName: 'Ember Twiddle',
types: ['sortMacro', 'simpleCP', 'complexCP'],
sortedBy: ['string'],
sortMacro: Ember.computed.sort('data', 'sortedBy'),
simpleCP: Ember.computed('data.[]', 'sortedBy', function() {
return this.get('data').sortBy(this.get('sortedBy')[0]);
}),
registerComplexCP(isInit) {
let sortedBy = this.get('sortedBy')[0];
this.set('complexCP', Ember.computed(`data.@each.${sortedBy}`, function() {
return this.get('data').sortBy(sortedBy);
}));
if (isInit) {
this.addObserver('sortedBy', this, 'registerComplexCP');
}
},
arraySize: 2000,
init() {
this._super(...arguments);
this.registerComplexCP(true);
let samples = Ember.Object.create();
let averages = Ember.Object.create();
this.get('types').forEach((type) => {
samples[type] = Ember.A();
});
this.setProperties({ samples, averages });
},
calcAverage(samples) {
let sum = samples.reduce((previousValue, currentValue) => {
return previousValue + currentValue;
}, 0);
let count = samples.get('length');
return Math.round(sum / count);
},
generateData() {
let data = [];
for (let i = 0; i < this.get('arraySize'); i++) {
const randomString = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
data.push({id: i, string: randomString});
}
return data;
},
run(type) {
this.set('data', this.generateData());
let start = performance.now();
this.get(type);
let delta = performance.now() - start;
this.get(`samples.${type}`).pushObject(delta);
},
actions: {
run(type) {
this.run(type);
this.set(`averages.${type}`, this.calcAverage(this.get(`samples.${type}`)));
},
runAll() {
let types = this.get('types');
for (let i = 1; i <= 10; i++) {
types.forEach((type) => {
this.send('run', type);
});
}
types.forEach((type) => {
this.set(`averages.${type}`, this.calcAverage(this.get(`samples.${type}`)));
});
}
}
});
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
table {
width: 100%;
}
table tbody tr td {
text-align: right;
}
.left {
text-align: left;
}
<h1>performance of ember's sort macro</h1>
<p>
Measuring performance of different approaches to sort an array in Ember.js
</p>
<p>
Length of array used: {{input value=arraySize}}
</p>
<table>
<thead>
<tr>
<th>type</th>
<th>samples</th>
<th>average</th>
<th>last run</th>
<th></th>
</tr>
</thead>
<tbody>
{{#each types as |type|}}
<tr>
<td class='left'>{{type}}</td>
<td>{{get samples (concat type '.length')}}</td>
<td>{{get averages type}}</td>
<td>{{get samples (concat type '.lastObject')}}</td>
<td><button onclick={{action 'run' type}}>run</button></td>
</tr>
{{/each}}
</tbody>
</table>
<p class='centered'>
<button onclick={{action 'runAll'}}>run all 10 times</button>
</p>
<h2>sortMacro</h2>
<pre>
Ember.Object.extend({
sortedBy: ['string'],
sortMacro: Ember.computed.sort('data', 'sortedBy')
});
</pre>
<h2>simpleCP</h2>
<pre>
Ember.Object.extend({
sortedBy: ['string'],
simpleCP: Ember.computed('data.[]', 'sortedBy', function() {
return this.get('data').sortBy(this.get('sortedBy')[0]);
})
});
</pre>
<p>Please note that this implementation is not as powerfull as the <i>sort</i> macro. It does not observe changes to field used for sortin (<i>sortedBy</i>) and properties of the objects being sorted. Also it does not support sorting by multiple fields and descending sorting.</p>
<h2>complexCP</h2>
<pre>
init() {
this._super(...arguments);
this.registerComplexCP(true);
},
registerComplexCP(isInit) {
let sortedBy = this.get('sortedBy')[0];
this.set('complexCP', Ember.computed(`data.@each.${sortedBy}`, function() {
return this.get('data').sortBy(sortedBy);
}));
if (isInit) {
this.addObserver('sortedBy', this, 'registerComplexCP');
}
}
</pre>
<p>While this implementation is more powerfull than <i>simpleCP</i> by observing changes to <i>sortedBy</i> and properties of objects being sorted, it's still not as powerfull as <i>sort</i> macro. Especially it does not support sorting by multiple fields and descending sorting.</p>
{
"version": "0.14.1",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js",
"ember": "2.18.2",
"ember-template-compiler": "2.18.2",
"ember-testing": "2.18.2"
},
"addons": {
"ember-data": "2.18.2"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment