Log top-level renders with console.time

Behind a flag.
This commit is contained in:
Ben Alpert
2015-12-01 11:29:13 -08:00
parent d01188133e
commit a0f88d29df
5 changed files with 121 additions and 0 deletions
+17
View File
@@ -19,6 +19,7 @@ var ReactDOMComponentTree = require('ReactDOMComponentTree');
var ReactDOMContainerInfo = require('ReactDOMContainerInfo');
var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
var ReactElement = require('ReactElement');
var ReactFeatureFlags = require('ReactFeatureFlags');
var ReactMarkupChecksum = require('ReactMarkupChecksum');
var ReactPerf = require('ReactPerf');
var ReactReconciler = require('ReactReconciler');
@@ -96,6 +97,17 @@ function mountComponentIntoNode(
shouldReuseMarkup,
context
) {
var markerName;
if (ReactFeatureFlags.logTopLevelRenders) {
var wrappedElement = wrapperInstance._currentElement.props;
var type = wrappedElement.type;
markerName = 'React mount: ' + (
typeof type === 'string' ? type :
type.displayName || type.name
);
console.time(markerName);
}
var markup = ReactReconciler.mountComponent(
wrapperInstance,
transaction,
@@ -103,6 +115,11 @@ function mountComponentIntoNode(
ReactDOMContainerInfo(wrapperInstance, container),
context
);
if (markerName) {
console.timeEnd(markerName);
}
wrapperInstance._renderedComponent._topLevelWrapper = wrapperInstance;
ReactMount._mountImageIntoNode(
markup,
@@ -279,4 +279,35 @@ describe('ReactMount', function() {
ReactDOM.unmountComponentAtNode(container);
expect(Object.keys(ReactMount._instancesByReactRootID).length).toBe(1);
});
it('marks top-level mounts', function() {
var ReactFeatureFlags = require('ReactFeatureFlags');
var Foo = React.createClass({
render: function() {
return <Bar />;
},
});
var Bar = React.createClass({
render: function() {
return <div />;
},
});
try {
ReactFeatureFlags.logTopLevelRenders = true;
spyOn(console, 'time');
spyOn(console, 'timeEnd');
ReactTestUtils.renderIntoDocument(<Foo />);
expect(console.time.argsForCall.length).toBe(1);
expect(console.time.argsForCall[0][0]).toBe('React mount: Foo');
expect(console.timeEnd.argsForCall.length).toBe(1);
expect(console.timeEnd.argsForCall[0][0]).toBe('React mount: Foo');
} finally {
ReactFeatureFlags.logTopLevelRenders = false;
}
});
});
@@ -13,6 +13,7 @@
var CallbackQueue = require('CallbackQueue');
var PooledClass = require('PooledClass');
var ReactFeatureFlags = require('ReactFeatureFlags');
var ReactPerf = require('ReactPerf');
var ReactReconciler = require('ReactReconciler');
var Transaction = require('Transaction');
@@ -149,11 +150,29 @@ function runBatchedUpdates(transaction) {
var callbacks = component._pendingCallbacks;
component._pendingCallbacks = null;
var markerName;
if (ReactFeatureFlags.logTopLevelRenders) {
var namedComponent = component;
// Duck type TopLevelWrapper. This is probably always true.
if (
component._currentElement.props ===
component._renderedComponent._currentElement
) {
namedComponent = component._renderedComponent;
}
markerName = 'React update: ' + namedComponent.getName();
console.time(markerName);
}
ReactReconciler.performUpdateIfNecessary(
component,
transaction.reconcileTransaction
);
if (markerName) {
console.timeEnd(markerName);
}
if (callbacks) {
for (var j = 0; j < callbacks.length; j++) {
transaction.callbackQueue.enqueue(
@@ -904,4 +904,37 @@ describe('ReactUpdates', function() {
expect(renderCount).toBe(1);
});
it('marks top-level updates', function() {
var ReactFeatureFlags = require('ReactFeatureFlags');
var Foo = React.createClass({
render: function() {
return <Bar />;
},
});
var Bar = React.createClass({
render: function() {
return <div />;
},
});
var container = document.createElement('div');
ReactDOM.render(<Foo />, container);
try {
ReactFeatureFlags.logTopLevelRenders = true;
spyOn(console, 'time');
spyOn(console, 'timeEnd');
ReactDOM.render(<Foo />, container);
expect(console.time.argsForCall.length).toBe(1);
expect(console.time.argsForCall[0][0]).toBe('React update: Foo');
expect(console.timeEnd.argsForCall.length).toBe(1);
expect(console.timeEnd.argsForCall[0][0]).toBe('React update: Foo');
} finally {
ReactFeatureFlags.logTopLevelRenders = false;
}
});
});
+21
View File
@@ -0,0 +1,21 @@
/**
* Copyright 2013-2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactFeatureFlags
*/
'use strict';
var ReactFeatureFlags = {
// When true, call console.time() before and .timeEnd() after each top-level
// render (both initial renders and updates). Useful when looking at prod-mode
// timeline profiles in Chrome, for example.
logTopLevelRenders: false,
};
module.exports = ReactFeatureFlags;