/** * @singleton * @private */Ext.define('Ext.perf.Monitor', { singleton: true, alternateClassName: 'Ext.Perf', requires: [ 'Ext.perf.Accumulator' ], constructor: function () { this.accumulators = []; this.accumulatorsByName = {}; }, calibrate: function () { var accum = new Ext.perf.Accumulator('$'), total = accum.total, getTimestamp = Ext.perf.Accumulator.getTimestamp, count = 0, frame, endTime, startTime; startTime = getTimestamp(); do { frame = accum.enter(); frame.leave(); ++count; } while (total.sum < 100); endTime = getTimestamp(); return (endTime - startTime) / count; }, get: function (name) { var me = this, accum = me.accumulatorsByName[name]; if (!accum) { me.accumulatorsByName[name] = accum = new Ext.perf.Accumulator(name); me.accumulators.push(accum); } return accum; }, enter: function (name) { return this.get(name).enter(); }, monitor: function (name, fn, scope) { this.get(name).monitor(fn, scope); }, report: function () { var me = this, accumulators = me.accumulators, calibration = me.calibrate(); accumulators.sort(function (a, b) { return (a.name < b.name) ? -1 : ((b.name < a.name) ? 1 : 0); }); me.updateGC(); Ext.log('Calibration: ' + Math.round(calibration * 100) / 100 + ' msec/sample'); Ext.each(accumulators, function (accum) { Ext.log(accum.format(calibration)); }); }, getData: function (all) { var ret = {}, accumulators = this.accumulators; Ext.each(accumulators, function (accum) { if (all || accum.count) { ret[accum.name] = accum.getData(); } }); return ret; }, reset: function(){ Ext.each(this.accumulators, function(accum){ var me = accum; me.count = me.childCount = me.depth = me.maxDepth = 0; me.pure = { min: Number.MAX_VALUE, max: 0, sum: 0 }; me.total = { min: Number.MAX_VALUE, max: 0, sum: 0 }; }); }, updateGC: function () { var accumGC = this.accumulatorsByName.GC, toolbox = Ext.senchaToolbox, bucket; if (accumGC) { accumGC.count = toolbox.garbageCollectionCounter || 0; if (accumGC.count) { bucket = accumGC.pure; accumGC.total.sum = bucket.sum = toolbox.garbageCollectionMilliseconds; bucket.min = bucket.max = bucket.sum / accumGC.count; bucket = accumGC.total; bucket.min = bucket.max = bucket.sum / accumGC.count; } } }, watchGC: function () { Ext.perf.getTimestamp(); // initializes SenchaToolbox (if available) var toolbox = Ext.senchaToolbox; if (toolbox) { this.get("GC"); toolbox.watchGarbageCollector(false); // no logging, just totals } }, setup: function (config) { if (!config) { config = { /*insertHtml: { 'Ext.dom.Helper': 'insertHtml' },*/ /*xtplCompile: { 'Ext.XTemplateCompiler': 'compile' },*/// doInsert: { // 'Ext.Template': 'doInsert' // }, // applyOut: { // 'Ext.XTemplate': 'applyOut' // }, render: { 'Ext.Component': 'render' },// fnishRender: { // 'Ext.Component': 'finishRender' // }, // renderSelectors: { // 'Ext.Component': 'applyRenderSelectors' // }, // compAddCls: { // 'Ext.Component': 'addCls' // }, // compRemoveCls: { // 'Ext.Component': 'removeCls' // }, // getStyle: { // 'Ext.core.Element': 'getStyle' // }, // setStyle: { // 'Ext.core.Element': 'setStyle' // }, // addCls: { // 'Ext.core.Element': 'addCls' // }, // removeCls: { // 'Ext.core.Element': 'removeCls' // }, // measure: { // 'Ext.layout.component.Component': 'measureAutoDimensions' // }, // moveItem: { // 'Ext.layout.Layout': 'moveItem' // }, // layoutFlush: { // 'Ext.layout.Context': 'flush' // }, layout: { 'Ext.layout.Context': 'run' } }; } this.currentConfig = config; var key, prop, accum, className, methods; for (key in config) { if (config.hasOwnProperty(key)) { prop = config[key]; accum = Ext.Perf.get(key); for (className in prop) { if (prop.hasOwnProperty(className)) { methods = prop[className]; accum.tap(className, methods); } } } } this.watchGC(); }});