react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / react-tools / src / test / ReactDefaultPerf.js
81152 views/**1* Copyright 2013-2014, Facebook, Inc.2* All rights reserved.3*4* This source code is licensed under the BSD-style license found in the5* LICENSE file in the root directory of this source tree. An additional grant6* of patent rights can be found in the PATENTS file in the same directory.7*8* @providesModule ReactDefaultPerf9* @typechecks static-only10*/1112"use strict";1314var DOMProperty = require('DOMProperty');15var ReactDefaultPerfAnalysis = require('ReactDefaultPerfAnalysis');16var ReactMount = require('ReactMount');17var ReactPerf = require('ReactPerf');1819var performanceNow = require('performanceNow');2021function roundFloat(val) {22return Math.floor(val * 100) / 100;23}2425function addValue(obj, key, val) {26obj[key] = (obj[key] || 0) + val;27}2829var ReactDefaultPerf = {30_allMeasurements: [], // last item in the list is the current one31_mountStack: [0],32_injected: false,3334start: function() {35if (!ReactDefaultPerf._injected) {36ReactPerf.injection.injectMeasure(ReactDefaultPerf.measure);37}3839ReactDefaultPerf._allMeasurements.length = 0;40ReactPerf.enableMeasure = true;41},4243stop: function() {44ReactPerf.enableMeasure = false;45},4647getLastMeasurements: function() {48return ReactDefaultPerf._allMeasurements;49},5051printExclusive: function(measurements) {52measurements = measurements || ReactDefaultPerf._allMeasurements;53var summary = ReactDefaultPerfAnalysis.getExclusiveSummary(measurements);54console.table(summary.map(function(item) {55return {56'Component class name': item.componentName,57'Total inclusive time (ms)': roundFloat(item.inclusive),58'Exclusive mount time (ms)': roundFloat(item.exclusive),59'Exclusive render time (ms)': roundFloat(item.render),60'Mount time per instance (ms)': roundFloat(item.exclusive / item.count),61'Render time per instance (ms)': roundFloat(item.render / item.count),62'Instances': item.count63};64}));65// TODO: ReactDefaultPerfAnalysis.getTotalTime() does not return the correct66// number.67},6869printInclusive: function(measurements) {70measurements = measurements || ReactDefaultPerf._allMeasurements;71var summary = ReactDefaultPerfAnalysis.getInclusiveSummary(measurements);72console.table(summary.map(function(item) {73return {74'Owner > component': item.componentName,75'Inclusive time (ms)': roundFloat(item.time),76'Instances': item.count77};78}));79console.log(80'Total time:',81ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'82);83},8485getMeasurementsSummaryMap: function(measurements) {86var summary = ReactDefaultPerfAnalysis.getInclusiveSummary(87measurements,88true89);90return summary.map(function(item) {91return {92'Owner > component': item.componentName,93'Wasted time (ms)': item.time,94'Instances': item.count95};96});97},9899printWasted: function(measurements) {100measurements = measurements || ReactDefaultPerf._allMeasurements;101console.table(ReactDefaultPerf.getMeasurementsSummaryMap(measurements));102console.log(103'Total time:',104ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'105);106},107108printDOM: function(measurements) {109measurements = measurements || ReactDefaultPerf._allMeasurements;110var summary = ReactDefaultPerfAnalysis.getDOMSummary(measurements);111console.table(summary.map(function(item) {112var result = {};113result[DOMProperty.ID_ATTRIBUTE_NAME] = item.id;114result['type'] = item.type;115result['args'] = JSON.stringify(item.args);116return result;117}));118console.log(119'Total time:',120ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'121);122},123124_recordWrite: function(id, fnName, totalTime, args) {125// TODO: totalTime isn't that useful since it doesn't count paints/reflows126var writes =127ReactDefaultPerf128._allMeasurements[ReactDefaultPerf._allMeasurements.length - 1]129.writes;130writes[id] = writes[id] || [];131writes[id].push({132type: fnName,133time: totalTime,134args: args135});136},137138measure: function(moduleName, fnName, func) {139return function(...args) {140var totalTime;141var rv;142var start;143144if (fnName === '_renderNewRootComponent' ||145fnName === 'flushBatchedUpdates') {146// A "measurement" is a set of metrics recorded for each flush. We want147// to group the metrics for a given flush together so we can look at the148// components that rendered and the DOM operations that actually149// happened to determine the amount of "wasted work" performed.150ReactDefaultPerf._allMeasurements.push({151exclusive: {},152inclusive: {},153render: {},154counts: {},155writes: {},156displayNames: {},157totalTime: 0158});159start = performanceNow();160rv = func.apply(this, args);161ReactDefaultPerf._allMeasurements[162ReactDefaultPerf._allMeasurements.length - 1163].totalTime = performanceNow() - start;164return rv;165} else if (moduleName === 'ReactDOMIDOperations' ||166moduleName === 'ReactComponentBrowserEnvironment') {167start = performanceNow();168rv = func.apply(this, args);169totalTime = performanceNow() - start;170171if (fnName === 'mountImageIntoNode') {172var mountID = ReactMount.getID(args[1]);173ReactDefaultPerf._recordWrite(mountID, fnName, totalTime, args[0]);174} else if (fnName === 'dangerouslyProcessChildrenUpdates') {175// special format176args[0].forEach(function(update) {177var writeArgs = {};178if (update.fromIndex !== null) {179writeArgs.fromIndex = update.fromIndex;180}181if (update.toIndex !== null) {182writeArgs.toIndex = update.toIndex;183}184if (update.textContent !== null) {185writeArgs.textContent = update.textContent;186}187if (update.markupIndex !== null) {188writeArgs.markup = args[1][update.markupIndex];189}190ReactDefaultPerf._recordWrite(191update.parentID,192update.type,193totalTime,194writeArgs195);196});197} else {198// basic format199ReactDefaultPerf._recordWrite(200args[0],201fnName,202totalTime,203Array.prototype.slice.call(args, 1)204);205}206return rv;207} else if (moduleName === 'ReactCompositeComponent' && (208fnName === 'mountComponent' ||209fnName === 'updateComponent' || // TODO: receiveComponent()?210fnName === '_renderValidatedComponent')) {211212var rootNodeID = fnName === 'mountComponent' ?213args[0] :214this._rootNodeID;215var isRender = fnName === '_renderValidatedComponent';216var isMount = fnName === 'mountComponent';217218var mountStack = ReactDefaultPerf._mountStack;219var entry = ReactDefaultPerf._allMeasurements[220ReactDefaultPerf._allMeasurements.length - 1221];222223if (isRender) {224addValue(entry.counts, rootNodeID, 1);225} else if (isMount) {226mountStack.push(0);227}228229start = performanceNow();230rv = func.apply(this, args);231totalTime = performanceNow() - start;232233if (isRender) {234addValue(entry.render, rootNodeID, totalTime);235} else if (isMount) {236var subMountTime = mountStack.pop();237mountStack[mountStack.length - 1] += totalTime;238addValue(entry.exclusive, rootNodeID, totalTime - subMountTime);239addValue(entry.inclusive, rootNodeID, totalTime);240} else {241addValue(entry.inclusive, rootNodeID, totalTime);242}243244entry.displayNames[rootNodeID] = {245current: this.constructor.displayName,246owner: this._owner ? this._owner.constructor.displayName : '<root>'247};248249return rv;250} else {251return func.apply(this, args);252}253};254}255};256257module.exports = ReactDefaultPerf;258259260