Skip to content

Commit

Permalink
Replace React debugging code with a User Timing polyfill for Fiber
Browse files Browse the repository at this point in the history
  • Loading branch information
gaearon committed Mar 8, 2017
1 parent 666a004 commit 4fb86f7
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 60 deletions.
3 changes: 3 additions & 0 deletions Libraries/Core/InitializeCore.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ if (!global.process.env.NODE_ENV) {
// Set up profile
const Systrace = require('Systrace');
Systrace.setEnabled(global.__RCTProfileIsProfiling || false);
if (__DEV__) {
global.performance = Systrace.getUserTimingPolyfill();
}

// Set up console
const ExceptionsManager = require('ExceptionsManager');
Expand Down
32 changes: 0 additions & 32 deletions Libraries/Performance/RCTRenderingPerf.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
*/
'use strict';

var ReactDebugTool = require('ReactDebugTool');
var ReactPerf = require('ReactPerf');

var invariant = require('fbjs/lib/invariant');
var performanceNow = require('fbjs/lib/performanceNow');

Expand All @@ -24,22 +21,6 @@ type perfModule = {

var perfModules = [];
var enabled = false;
var lastRenderStartTime = 0;
var totalRenderDuration = 0;

var RCTRenderingPerfDevtool = {
onBeginLifeCycleTimer(debugID, timerType) {
if (timerType === 'render') {
lastRenderStartTime = performanceNow();
}
},
onEndLifeCycleTimer(debugID, timerType) {
if (timerType === 'render') {
var lastRenderDuration = performanceNow() - lastRenderStartTime;
totalRenderDuration += lastRenderDuration;
}
},
};

var RCTRenderingPerf = {
// Once perf is enabled, it stays enabled
Expand All @@ -52,26 +33,13 @@ var RCTRenderingPerf = {
if (!enabled) {
return;
}

ReactPerf.start();
ReactDebugTool.addHook(RCTRenderingPerfDevtool);
perfModules.forEach((module) => module.start());
},

stop: function() {
if (!enabled) {
return;
}

ReactPerf.stop();
ReactPerf.printInclusive();
ReactPerf.printWasted();
ReactDebugTool.removeHook(RCTRenderingPerfDevtool);

console.log(`Total time spent in render(): ${totalRenderDuration.toFixed(2)} ms`);
lastRenderStartTime = 0;
totalRenderDuration = 0;

perfModules.forEach((module) => module.stop());
},

Expand Down
78 changes: 50 additions & 28 deletions Libraries/Performance/Systrace.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
*/
'use strict';

const invariant = require('invariant');

type RelayProfiler = {
attachProfileHandler(
name: string,
Expand All @@ -30,47 +32,67 @@ const TRACE_TAG_JSC_CALLS = 1 << 27;
let _enabled = false;
let _asyncCookie = 0;

const ReactSystraceDevtool = __DEV__ ? {
onBeforeMountComponent(debugID) {
const displayName = require('react/lib/ReactComponentTreeHook').getDisplayName(debugID);
Systrace.beginEvent(`ReactReconciler.mountComponent(${displayName})`);
},
onMountComponent(debugID) {
Systrace.endEvent();
},
onBeforeUpdateComponent(debugID) {
const displayName = require('react/lib/ReactComponentTreeHook').getDisplayName(debugID);
Systrace.beginEvent(`ReactReconciler.updateComponent(${displayName})`);
},
onUpdateComponent(debugID) {
Systrace.endEvent();
},
onBeforeUnmountComponent(debugID) {
const displayName = require('react/lib/ReactComponentTreeHook').getDisplayName(debugID);
Systrace.beginEvent(`ReactReconciler.unmountComponent(${displayName})`);
let _markStack = [];
let _markStackIndex = -1;

const userTimingPolyfill = {
mark(markName : string) {
if (__DEV__) {
if (_enabled) {
_markStackIndex++;
_markStack[_markStackIndex] = markName;
let label = markName;
if (markName[0] === '\u269B') {
// This is coming from React.
// Remove emoji and component IDs.
const indexOfId = markName.lastIndexOf(' (#');
const cutoffIndex = indexOfId !== -1 ? indexOfId : markName.length;
label = markName.slice(2, cutoffIndex);
}
Systrace.beginEvent(label);
}
}
},
onUnmountComponent(debugID) {
Systrace.endEvent();
measure(label : string, markName : string) {
if (__DEV__) {
if (_enabled) {
invariant(markName === _markStack[_markStackIndex], 'Unexpected measure() call.');
// TODO: it would be nice to use `label` because it is more friendly.
// I don't know if there's a way to annotate measurements post factum.
_markStackIndex--;
Systrace.endEvent();
}
}
},
onBeginLifeCycleTimer(debugID, timerType) {
const displayName = require('react/lib/ReactComponentTreeHook').getDisplayName(debugID);
Systrace.beginEvent(`${displayName}.${timerType}()`);
clearMarks(markName : string) {
if (__DEV__) {
if (_enabled) {
if (_markStackIndex > -1 && markName === _markStack[_markStackIndex]) {
_markStackIndex--;
// TODO: ideally this event shouldn't show up in the first place.
// I don't know if there's a way to cancel an ongoing measurement.
Systrace.endEvent();
}
}
}
},
onEndLifeCycleTimer(debugID, timerType) {
Systrace.endEvent();
clearMeasures() {
// Noop.
},
} : null;
};

const Systrace = {
getUserTimingPolyfill() {
return userTimingPolyfill;
},

setEnabled(enabled: boolean) {
if (_enabled !== enabled) {
if (__DEV__) {
if (enabled) {
global.nativeTraceBeginLegacy && global.nativeTraceBeginLegacy(TRACE_TAG_JSC_CALLS);
require('ReactDebugTool').addHook(ReactSystraceDevtool);
} else {
global.nativeTraceEndLegacy && global.nativeTraceEndLegacy(TRACE_TAG_JSC_CALLS);
require('ReactDebugTool').removeHook(ReactSystraceDevtool);
}
}
_enabled = enabled;
Expand Down

0 comments on commit 4fb86f7

Please sign in to comment.