choo-shortcache
Version:
choo nanocomponent cache shortcut
140 lines (117 loc) • 3.7 kB
JavaScript
var onPerformance = require('on-performance')
var BAR = '█'
module.exports = perf
function perf (state, emitter, app, localEmitter) {
var stats = {}
window.choo.perf = {}
// Print all events
var all = new Perf(stats, 'all')
Object.defineProperty(window.choo.perf, 'all', {
get: all.get.bind(all),
set: noop
})
// Print only Choo core events
var core = new Perf(stats, 'core', function (name) {
return /^choo/.test(name)
})
Object.defineProperty(window.choo.perf, 'core', {
get: core.get.bind(core),
set: noop
})
// Print component data
var components = new Perf(stats, 'components', function (name) {
return !/^choo/.test(name) && !/^bankai/.test(name)
})
Object.defineProperty(window.choo.perf, 'components', {
get: components.get.bind(components),
set: noop
})
// Print choo userland events (event emitter)
var events = new Perf(stats, 'events', function (name) {
return /^choo\.emit/.test(name)
}, function (name) {
return name.replace(/^choo\.emit\('/, '').replace(/'\)$/, '')
})
Object.defineProperty(window.choo.perf, 'events', {
get: events.get.bind(events),
set: noop
})
onPerformance(function (entry) {
if (entry.entryType !== 'measure') return
var name = entry.name.replace(/ .*$/, '')
if (!stats[name]) {
stats[name] = {
name: name,
count: 0,
entries: []
}
}
var stat = stats[name]
stat.count += 1
stat.entries.push(entry.duration)
})
}
// Create a new Perf instance by passing it a filter
function Perf (stats, name, filter, rename) {
this.stats = stats
this.name = name
this.filter = filter || function () { return true }
this.rename = rename || function (name) { return name }
}
// Compute a table of performance entries based on a filter
Perf.prototype.get = function () {
var filtered = Object.keys(this.stats).filter(this.filter)
var self = this
var maxTime = 0
var maxMedian = 0
var fmt = filtered.map(function (key) {
var stat = self.stats[key]
var totalTime = Number(stat.entries.reduce(function (time, entry) {
return time + entry
}, 0).toFixed(2))
if (totalTime > maxTime) maxTime = totalTime
var median = getMedian(stat.entries)
if (median > maxMedian) maxMedian = median
var name = self.rename(stat.name)
return new PerfEntry(name, totalTime, median, stat.count)
})
var barLength = 10
fmt.forEach(function (entry) {
var totalTime = entry['Total Time (ms)']
var median = entry['Median (ms)']
entry[' '] = createBar(totalTime / maxTime * 100 / barLength)
entry[' '] = createBar(median / maxMedian * 100 / barLength)
})
function createBar (len) {
var str = ''
for (var i = 0, max = Math.round(len); i < max; i++) {
str += BAR
}
return str
}
var res = fmt.sort(function (a, b) {
return b['Total Time (ms)'] - a['Total Time (ms)']
})
console.table(res)
return "Showing performance events for '" + this.name + "'"
}
// An entry for the performance timeline.
function PerfEntry (name, totalTime, median, count) {
this['Name'] = name
this['Total Time (ms)'] = totalTime
this[' '] = 0
this['Median (ms)'] = median
this[' '] = 0
this['Total Count'] = count
}
// Get the median from an array of numbers.
function getMedian (args) {
if (!args.length) return 0
var numbers = args.slice(0).sort(function (a, b) { return a - b })
var middle = Math.floor(numbers.length / 2)
var isEven = numbers.length % 2 === 0
var res = isEven ? (numbers[middle] + numbers[middle - 1]) / 2 : numbers[middle]
return Number(res.toFixed(2))
}
// Do nothing.
function noop () {}