Updates to perf
ReactDefaultPerf: * Show times as float instead of string. This means they're sortable. * Add count columns to all types and average to exclusive time. * Include mountComponent where updateComponent time is measured. * Increment count on _renderValidatedComponent instead of update. ReactDefaultPerfAnalysis: * Return counts with all summaries.
Josh Duck committed
Feb 13, 2014 at 18:11 UTC
acbba1ae6720612019c1afbeafc08b6e2153e261
2 files changed
+55
-39
src/test/ReactDefaultPerf.js
+29
-16
@@ -26,8 +26,12 @@ var ReactPerf = require('ReactPerf');
26
27
var performanceNow = require('performanceNow');
28
29
+function roundFloat(val) {
30
+ return Math.floor(val * 100) / 100;
31
+}
32
+
33
var ReactDefaultPerf = {
30
- _allMeasurements: null, // last item in the list is the current one
34
+ _allMeasurements: [], // last item in the list is the current one
35
_injected: false,
36
37
start: function() {
@@ -35,7 +39,7 @@ var ReactDefaultPerf = {
39
ReactPerf.injection.injectMeasure(ReactDefaultPerf.measure);
40
}
41
38
- ReactDefaultPerf._allMeasurements = [];
42
+ ReactDefaultPerf._allMeasurements.length = 0;
43
ReactPerf.enableMeasure = true;
44
},
45
@@ -53,8 +57,10 @@ var ReactDefaultPerf = {
57
console.table(summary.map(function(item) {
58
return {
59
'Component class name': item.componentName,
56
- 'Exclusive time': item.exclusiveTime.toFixed(2) + ' ms',
57
- 'Inclusive time': item.inclusiveTime.toFixed(2) + ' ms'
60
+ 'Total inclusive time (ms)': roundFloat(item.inclusive),
61
+ 'Total exclusive time (ms)': roundFloat(item.exclusive),
62
+ 'Exclusive time per instance (ms)': roundFloat(item.exclusive / item.count),
63
+ 'Instances': item.count
64
};
65
}));
66
console.log(
@@ -69,7 +75,8 @@ var ReactDefaultPerf = {
75
console.table(summary.map(function(item) {
76
return {
77
'Owner > component': item.componentName,
72
- 'Inclusive time': item.inclusiveTime.toFixed(2) + ' ms'
78
+ 'Inclusive time (ms)': roundFloat(item.time),
79
+ 'Instances': item.count
80
};
81
}));
82
console.log(
@@ -87,7 +94,8 @@ var ReactDefaultPerf = {
94
console.table(summary.map(function(item) {
95
return {
96
'Owner > component': item.componentName,
90
- 'Wasted time': item.inclusiveTime.toFixed(2) + ' ms'
97
+ 'Wasted time (ms)': item.time,
98
+ 'Instances': item.count
99
};
100
}));
101
console.log(
@@ -195,27 +203,32 @@ var ReactDefaultPerf = {
203
}
204
return rv;
205
} else if (moduleName === 'ReactCompositeComponent' && (
206
+ fnName === 'mountComponent' ||
207
fnName === 'updateComponent' || // TODO: receiveComponent()?
208
fnName === '_renderValidatedComponent')) {
200
- var isInclusive = fnName === 'updateComponent';
209
+
210
+ var rootNodeID = fnName === 'mountComponent' ?
211
+ args[0] :
212
+ this._rootNodeID;
213
+ var isRender = fnName === '_renderValidatedComponent';
214
var entry = ReactDefaultPerf._allMeasurements[
215
ReactDefaultPerf._allMeasurements.length - 1
216
];
204
- if (isInclusive) {
205
- // Since both updateComponent() and _renderValidatedComponent() are
206
- // called for each render, only record the count for one of them.
207
- entry.counts[this._rootNodeID] = entry.counts[this._rootNodeID] || 0;
208
- entry.counts[this._rootNodeID] += 1;
217
+
218
+ if (isRender) {
219
+ entry.counts[rootNodeID] = entry.counts[rootNodeID] || 0;
220
+ entry.counts[rootNodeID] += 1;
221
}
222
+
223
start = performanceNow();
224
rv = func.apply(this, args);
225
totalTime = performanceNow() - start;
226
214
- var typeOfLog = isInclusive ? entry.inclusive : entry.exclusive;
215
- typeOfLog[this._rootNodeID] = typeOfLog[this._rootNodeID] || 0;
216
- typeOfLog[this._rootNodeID] += totalTime;
227
+ var typeOfLog = isRender ? entry.exclusive : entry.inclusive;
228
+ typeOfLog[rootNodeID] = typeOfLog[rootNodeID] || 0;
229
+ typeOfLog[rootNodeID] += totalTime;
230
218
- entry.displayNames[this._rootNodeID] = {
231
+ entry.displayNames[rootNodeID] = {
232
current: this.constructor.displayName,
233
owner: this._owner ? this._owner.constructor.displayName : '<root>'
234
};
src/test/ReactDefaultPerfAnalysis.js
+26
-23
@@ -77,8 +77,10 @@ function getExclusiveSummary(measurements) {
77
displayName = measurement.displayNames[id].current;
78
79
candidates[displayName] = candidates[displayName] || {
80
+ componentName: displayName,
81
inclusive: 0,
81
- exclusive: 0
82
+ exclusive: 0,
83
+ count: 0
84
};
85
if (measurement.exclusive[id]) {
86
candidates[displayName].exclusive += measurement.exclusive[id];
@@ -86,32 +88,30 @@ function getExclusiveSummary(measurements) {
88
if (measurement.inclusive[id]) {
89
candidates[displayName].inclusive += measurement.inclusive[id];
90
}
91
+ if (measurement.counts[id]) {
92
+ candidates[displayName].count += measurement.counts[id];
93
+ }
94
}
95
}
96
97
// Now make a sorted array with the results.
98
var arr = [];
99
for (displayName in candidates) {
95
- if (candidates[displayName].exclusiveTime < DONT_CARE_THRESHOLD) {
96
- continue;
100
+ if (candidates[displayName].exclusive >= DONT_CARE_THRESHOLD) {
101
+ arr.push(candidates[displayName]);
102
}
98
- arr.push({
99
- componentName: displayName,
100
- exclusiveTime: candidates[displayName].exclusive,
101
- inclusiveTime: candidates[displayName].inclusive
102
- });
103
}
104
105
arr.sort(function(a, b) {
106
- return b.exclusiveTime - a.exclusiveTime;
106
+ return b.exclusive - a.exclusive;
107
});
108
109
return arr;
110
}
111
112
function getInclusiveSummary(measurements, onlyClean) {
113
- var inclusiveTimes = {};
114
- var displayName;
113
+ var candidates = {};
114
+ var inclusiveKey;
115
116
for (var i = 0; i < measurements.length; i++) {
117
var measurement = measurements[i];
@@ -127,35 +127,38 @@ function getInclusiveSummary(measurements, onlyClean) {
127
continue;
128
}
129
130
- displayName = measurement.displayNames[id];
130
+ var displayName = measurement.displayNames[id];
131
132
// Inclusive time is not useful for many components without knowing where
133
// they are instantiated. So we aggregate inclusive time with both the
134
// owner and current displayName as the key.
135
- var inclusiveKey = displayName.owner + ' > ' + displayName.current;
135
+ inclusiveKey = displayName.owner + ' > ' + displayName.current;
136
137
- inclusiveTimes[inclusiveKey] = inclusiveTimes[inclusiveKey] || 0;
137
+ candidates[inclusiveKey] = candidates[inclusiveKey] || {
138
+ componentName: inclusiveKey,
139
+ time: 0,
140
+ count: 0
141
+ };
142
143
if (measurement.inclusive[id]) {
140
- inclusiveTimes[inclusiveKey] += measurement.inclusive[id];
144
+ candidates[inclusiveKey].time += measurement.inclusive[id];
145
+ }
146
+ if (measurement.counts[id]) {
147
+ candidates[inclusiveKey].count += measurement.counts[id];
148
}
149
}
150
}
151
152
// Now make a sorted array with the results.
153
var arr = [];
147
- for (displayName in inclusiveTimes) {
148
- if (inclusiveTimes[displayName] < DONT_CARE_THRESHOLD) {
149
- continue;
154
+ for (inclusiveKey in candidates) {
155
+ if (candidates[inclusiveKey].time >= DONT_CARE_THRESHOLD) {
156
+ arr.push(candidates[inclusiveKey]);
157
}
151
- arr.push({
152
- componentName: displayName,
153
- inclusiveTime: inclusiveTimes[displayName]
154
- });
158
}
159
160
arr.sort(function(a, b) {
158
- return b.inclusiveTime - a.inclusiveTime;
161
+ return b.time - a.time;
162
});
163
164
return arr;