react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / react-tools / src / test / ReactDefaultPerfAnalysis.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 ReactDefaultPerfAnalysis9*/1011var assign = require('Object.assign');1213// Don't try to save users less than 1.2ms (a number I made up)14var DONT_CARE_THRESHOLD = 1.2;15var DOM_OPERATION_TYPES = {16'mountImageIntoNode': 'set innerHTML',17INSERT_MARKUP: 'set innerHTML',18MOVE_EXISTING: 'move',19REMOVE_NODE: 'remove',20TEXT_CONTENT: 'set textContent',21'updatePropertyByID': 'update attribute',22'deletePropertyByID': 'delete attribute',23'updateStylesByID': 'update styles',24'updateInnerHTMLByID': 'set innerHTML',25'dangerouslyReplaceNodeWithMarkupByID': 'replace'26};2728function getTotalTime(measurements) {29// TODO: return number of DOM ops? could be misleading.30// TODO: measure dropped frames after reconcile?31// TODO: log total time of each reconcile and the top-level component32// class that triggered it.33var totalTime = 0;34for (var i = 0; i < measurements.length; i++) {35var measurement = measurements[i];36totalTime += measurement.totalTime;37}38return totalTime;39}4041function getDOMSummary(measurements) {42var items = [];43for (var i = 0; i < measurements.length; i++) {44var measurement = measurements[i];45var id;4647for (id in measurement.writes) {48measurement.writes[id].forEach(function(write) {49items.push({50id: id,51type: DOM_OPERATION_TYPES[write.type] || write.type,52args: write.args53});54});55}56}57return items;58}5960function getExclusiveSummary(measurements) {61var candidates = {};62var displayName;6364for (var i = 0; i < measurements.length; i++) {65var measurement = measurements[i];66var allIDs = assign(67{},68measurement.exclusive,69measurement.inclusive70);7172for (var id in allIDs) {73displayName = measurement.displayNames[id].current;7475candidates[displayName] = candidates[displayName] || {76componentName: displayName,77inclusive: 0,78exclusive: 0,79render: 0,80count: 081};82if (measurement.render[id]) {83candidates[displayName].render += measurement.render[id];84}85if (measurement.exclusive[id]) {86candidates[displayName].exclusive += measurement.exclusive[id];87}88if (measurement.inclusive[id]) {89candidates[displayName].inclusive += measurement.inclusive[id];90}91if (measurement.counts[id]) {92candidates[displayName].count += measurement.counts[id];93}94}95}9697// Now make a sorted array with the results.98var arr = [];99for (displayName in candidates) {100if (candidates[displayName].exclusive >= DONT_CARE_THRESHOLD) {101arr.push(candidates[displayName]);102}103}104105arr.sort(function(a, b) {106return b.exclusive - a.exclusive;107});108109return arr;110}111112function getInclusiveSummary(measurements, onlyClean) {113var candidates = {};114var inclusiveKey;115116for (var i = 0; i < measurements.length; i++) {117var measurement = measurements[i];118var allIDs = assign(119{},120measurement.exclusive,121measurement.inclusive122);123var cleanComponents;124125if (onlyClean) {126cleanComponents = getUnchangedComponents(measurement);127}128129for (var id in allIDs) {130if (onlyClean && !cleanComponents[id]) {131continue;132}133134var displayName = measurement.displayNames[id];135136// Inclusive time is not useful for many components without knowing where137// they are instantiated. So we aggregate inclusive time with both the138// owner and current displayName as the key.139inclusiveKey = displayName.owner + ' > ' + displayName.current;140141candidates[inclusiveKey] = candidates[inclusiveKey] || {142componentName: inclusiveKey,143time: 0,144count: 0145};146147if (measurement.inclusive[id]) {148candidates[inclusiveKey].time += measurement.inclusive[id];149}150if (measurement.counts[id]) {151candidates[inclusiveKey].count += measurement.counts[id];152}153}154}155156// Now make a sorted array with the results.157var arr = [];158for (inclusiveKey in candidates) {159if (candidates[inclusiveKey].time >= DONT_CARE_THRESHOLD) {160arr.push(candidates[inclusiveKey]);161}162}163164arr.sort(function(a, b) {165return b.time - a.time;166});167168return arr;169}170171function getUnchangedComponents(measurement) {172// For a given reconcile, look at which components did not actually173// render anything to the DOM and return a mapping of their ID to174// the amount of time it took to render the entire subtree.175var cleanComponents = {};176var dirtyLeafIDs = Object.keys(measurement.writes);177var allIDs = assign({}, measurement.exclusive, measurement.inclusive);178179for (var id in allIDs) {180var isDirty = false;181// For each component that rendered, see if a component that triggered182// a DOM op is in its subtree.183for (var i = 0; i < dirtyLeafIDs.length; i++) {184if (dirtyLeafIDs[i].indexOf(id) === 0) {185isDirty = true;186break;187}188}189if (!isDirty && measurement.counts[id] > 0) {190cleanComponents[id] = true;191}192}193return cleanComponents;194}195196var ReactDefaultPerfAnalysis = {197getExclusiveSummary: getExclusiveSummary,198getInclusiveSummary: getInclusiveSummary,199getDOMSummary: getDOMSummary,200getTotalTime: getTotalTime201};202203module.exports = ReactDefaultPerfAnalysis;204205206