@samitouri / QOS-React-2 / commits / 94ef6c51fb

[perf] Better inclusive measurements

Inclusive time is still not that helpful w/o looking at what actually resulted in DOM ops. However, this is better than what we have today and will serve as a building block. I blacklisted everything but composite components -- hopefully that's OK.

Pete Hunt committed Feb 12, 2014 at 15:51 UTC 94ef6c51fb9145e0bc445145d394f3ef1b13804a
1 file changed +88 -29
src/test/ReactDefaultPerf.js
+88 -29
@@ -26,11 +26,8 @@ var performanceNow = require('performanceNow');
26 // Don't try to save users less than 1.2ms (a number I made up)
27 var DONT_CARE_THRESHOLD = 1.2;
28
29 -function getSummary(measurements, sortInclusive) {
30 - var candidates = {};
29 +function getTotalDOMTime(measurements) {
30 var totalDOMTime = 0;
32 - var displayName;
33 -
31 for (var i = 0; i < measurements.length; i++) {
32 var measurement = measurements[i];
33 var id;
@@ -40,11 +37,21 @@ function getSummary(measurements, sortInclusive) {
37 totalDOMTime += write.time;
38 });
39 }
40 + }
41 + return totalDOMTime;
42 +}
43 +
44 +function getExclusiveSummary(measurements) {
45 + var candidates = {};
46 + var displayName;
47
48 + for (var i = 0; i < measurements.length; i++) {
49 + var measurement = measurements[i];
50 var allIDs = merge(measurement.exclusive, measurement.inclusive);
51
46 - for (id in allIDs) {
47 - displayName = measurement.displayNames[id];
52 + for (var id in allIDs) {
53 + displayName = measurement.displayNames[id].current;
54 +
55 candidates[displayName] = candidates[displayName] || {
56 inclusive: 0,
57 exclusive: 0
@@ -61,7 +68,7 @@ function getSummary(measurements, sortInclusive) {
68 // Now make a sorted array with the results.
69 var arr = [];
70 for (displayName in candidates) {
64 - if (candidates[displayName] < DONT_CARE_THRESHOLD) {
71 + if (candidates[displayName].exclusiveTime < DONT_CARE_THRESHOLD) {
72 continue;
73 }
74 arr.push({
@@ -71,17 +78,55 @@ function getSummary(measurements, sortInclusive) {
78 });
79 }
80
74 - if (sortInclusive) {
75 - arr.sort(function(a, b) {
76 - return b.inclusiveTime - a.inclusiveTime;
77 - });
78 - } else {
79 - arr.sort(function(a, b) {
80 - return b.exclusiveTime - a.exclusiveTime;
81 + arr.sort(function(a, b) {
82 + return b.exclusiveTime - a.exclusiveTime;
83 + });
84 +
85 + return arr;
86 +}
87 +
88 +function getInclusiveSummary(measurements) {
89 + var inclusiveTimes = {};
90 + var displayName;
91 +
92 + for (var i = 0; i < measurements.length; i++) {
93 + var measurement = measurements[i];
94 + var allIDs = merge(measurement.exclusive, measurement.inclusive);
95 +
96 +
97 + for (var id in allIDs) {
98 + displayName = measurement.displayNames[id];
99 +
100 + // Inclusive time is not useful for many components without knowing where
101 + // they are instantiated. So we aggregate inclusive time with both the
102 + // owner and current displayName as the key.
103 + var inclusiveKey = displayName.owner + ' > ' + displayName.current;
104 +
105 + inclusiveTimes[inclusiveKey] = inclusiveTimes[inclusiveKey] || 0;
106 +
107 + if (measurement.inclusive[id]) {
108 + inclusiveTimes[inclusiveKey] += measurement.inclusive[id];
109 + }
110 + }
111 + }
112 +
113 + // Now make a sorted array with the results.
114 + var arr = [];
115 + for (displayName in inclusiveTimes) {
116 + if (inclusiveTimes[displayName] < DONT_CARE_THRESHOLD) {
117 + continue;
118 + }
119 + arr.push({
120 + componentName: displayName,
121 + inclusiveTime: inclusiveTimes[displayName]
122 });
123 }
124
84 - return {componentClasses: arr, totalDOMTime: totalDOMTime};
125 + arr.sort(function(a, b) {
126 + return b.inclusiveTime - a.inclusiveTime;
127 + });
128 +
129 + return arr;
130 }
131
132 var ReactDefaultPerf = {
@@ -106,24 +151,34 @@ var ReactDefaultPerf = {
151 },
152
153 printByExclusive: function(measurements) {
109 - ReactDefaultPerf.print(measurements, false);
154 + measurements = measurements || ReactDefaultPerf._allMeasurements;
155 + var summary = getExclusiveSummary(measurements);
156 + console.table(summary.map(function(item) {
157 + return {
158 + 'Component class name': item.componentName,
159 + 'Exclusive time': item.exclusiveTime.toFixed(2) + ' ms',
160 + 'Inclusive time': item.inclusiveTime.toFixed(2) + ' ms'
161 + };
162 + }));
163 + console.log(
164 + 'Total DOM time:',
165 + getTotalDOMTime(measurements).toFixed(2) + ' ms'
166 + );
167 },
168
169 printByInclusive: function(measurements) {
113 - ReactDefaultPerf.print(measurements, true);
114 - },
115 -
116 - print: function(measurements, sortInclusive) {
170 measurements = measurements || ReactDefaultPerf._allMeasurements;
118 - var summary = getSummary(measurements, sortInclusive);
119 - console.table(summary.componentClasses.map(function(item) {
171 + var summary = getInclusiveSummary(measurements);
172 + console.table(summary.map(function(item) {
173 return {
121 - 'Component class name': item.componentName,
122 - 'Inclusive time': item.inclusiveTime.toFixed(2) + ' ms',
123 - 'Exclusive time': item.exclusiveTime.toFixed(2) + ' ms'
174 + 'Owner > component': item.componentName,
175 + 'Inclusive time': item.inclusiveTime.toFixed(2) + ' ms'
176 };
177 }));
126 - console.log('Total DOM time:', summary.totalDOMTime.toFixed(2) + ' ms');
178 + console.log(
179 + 'Total DOM time:',
180 + getTotalDOMTime(measurements).toFixed(2) + ' ms'
181 + );
182 },
183
184 _recordWrite: function(id, fnName, totalTime) {
@@ -176,8 +231,9 @@ var ReactDefaultPerf = {
231 ReactDefaultPerf._recordWrite(args[0], fnName, totalTime);
232 }
233 return rv;
179 - } else if (fnName === 'updateComponent' ||
180 - fnName === '_renderValidatedComponent') {
234 + } else if (moduleName === 'ReactCompositeComponent' && (
235 + fnName === 'updateComponent' ||
236 + fnName === '_renderValidatedComponent')) {
237 var isInclusive = fnName === 'updateComponent';
238 var entry = ReactDefaultPerf._allMeasurements[
239 ReactDefaultPerf._allMeasurements.length - 1
@@ -196,7 +252,10 @@ var ReactDefaultPerf = {
252 typeOfLog[this._rootNodeID] = typeOfLog[this._rootNodeID] || 0;
253 typeOfLog[this._rootNodeID] += totalTime;
254
199 - entry.displayNames[this._rootNodeID] = this.constructor.displayName;
255 + entry.displayNames[this._rootNodeID] = {
256 + current: this.constructor.displayName,
257 + owner: this._owner ? this._owner.constructor.displayName : '<root>'
258 + };
259
260 return rv;
261 } else {