function resetMeasurements() { var previousStartTime = currentFlushStartTime; var previousMeasurements = currentFlushMeasurements || []; var previousOperations = ReactHostOperationHistoryDevtool.getHistory(); if (currentFlushNesting === 0) { currentFlushStartTime = null; currentFlushMeasurements = null; clearHistory(); return; } if (previousMeasurements.length || previousOperations.length) { var registeredIDs = ReactComponentTreeDevtool.getRegisteredIDs(); flushHistory.push({ duration: performanceNow() - previousStartTime, measurements: previousMeasurements || [], operations: previousOperations || [], treeSnapshot: getTreeSnapshot(registeredIDs), }); } clearHistory(); currentFlushStartTime = performanceNow(); currentFlushMeasurements = []; }
constructor(props, context) { super(props, context); this.state = { ctorTimestamp: performanceNow(), timeToMount: 0, }; }
function endLifeCycleTimer(debugID, timerType) { if (currentFlushNesting === 0) { return; } if (currentTimerType !== timerType && !lifeCycleTimerHasWarned) { warning( false, 'There is an internal error in the React performance measurement code. ' + 'We did not expect %s timer to stop while %s timer is still in ' + 'progress for %s instance. Please report this as a bug in React.', timerType, currentTimerType || 'no', (debugID === currentTimerDebugID) ? 'the same' : 'another' ); lifeCycleTimerHasWarned = true; } if (isProfiling) { currentFlushMeasurements.push({ timerType, instanceID: debugID, duration: performanceNow() - currentTimerStartTime - currentTimerNestedFlushDuration, }); } currentTimerStartTime = null; currentTimerNestedFlushDuration = null; currentTimerDebugID = null; currentTimerType = null; }
constructor(props: mixed, context: mixed) { super(props, context); this.start = performanceNow(); this.state = { stats: null, }; (this: any)._onDone = this._onDone.bind(this); }
function resumeCurrentLifeCycleTimer() { var {startTime, nestedFlushStartTime, debugID, timerType} = lifeCycleTimerStack.pop(); var nestedFlushDuration = performanceNow() - nestedFlushStartTime; currentTimerStartTime = startTime; currentTimerNestedFlushDuration += nestedFlushDuration; currentTimerDebugID = debugID; currentTimerType = timerType; }
function markBegin(debugID, markType) { if (!shouldMark(debugID)) { return; } var markName = `${debugID}::${markType}`; lastMarkTimeStamp = performanceNow(); performance.mark(markName); }
constructor() { this._initTime = performanceNow(); this._queryID = 0; this._subscription = Relay.Store.addNetworkSubscriber( request => this.logRequest(createDebuggableFromRequest('Relay Query', request)), request => this.logRequest(createDebuggableFromRequest('Relay Mutation', request)) ); }
return function(...args) { var timeBeforeFn = performanceNow(); var fnReturn = func.apply(this, args); var timeAfterFn = performanceNow(); /** * Hold onto arguments in a readable way: args[1] -> args.component. * args is also passed to the callback, so if you want to save an * argument in the log, do so in the callback. */ var argsObject = {}; for (var i = 0; i < args.length; i++) { argsObject[fnArgs[i]] = args[i]; } var log = { index: ReactDefaultPerf.logs.length, fnName: fnName, objName: objName, timing: { before: timeBeforeFn, after: timeAfterFn, delta: timeAfterFn - timeBeforeFn } }; ReactDefaultPerf.logs.push(log); /** * The callback gets: * - this (the component) * - the original method's arguments * - what the method returned * - the log object, and * - the wrapped method's info object. */ var callback = _getCallback(objName, fnName); callback && callback(this, argsObject, fnReturn, log, info); log.timing.timeToLog = performanceNow() - timeAfterFn; return fnReturn; };
const onSettled = (error, response) => { const time = (performanceNow() - this._initTime) / 1000; console.timeStamp(`← END: [${id}] ${type}: ${name}`); console.groupCollapsed( `%c[${id}] ${type}: ${name} @ ${time}s`, `color:${error ? 'red' : 'black'};` ); console.timeEnd(timerName); logResult(error, response); console.groupEnd(); };
setTimeout(() => { const stats = { onDoneElapsed, totalWidgets, ...JSEventLoopWatchdog.getStats(), setTimeoutElapsed: performanceNow() - this.start, }; stats.avgStall = stats.totalStallTime / stats.stallCount; this.setState({stats}); console.log('onDone:', stats); }, 0);
function resetMeasurements() { if (__DEV__) { if (!isProfiling || currentFlushNesting === 0) { currentFlushStartTime = null; currentFlushMeasurements = null; return; } var previousStartTime = currentFlushStartTime; var previousMeasurements = currentFlushMeasurements || []; var previousOperations = ReactNativeOperationHistoryDevtool.getHistory(); if (previousMeasurements.length || previousOperations.length) { var registeredIDs = ReactComponentTreeDevtool.getRegisteredIDs(); flushHistory.push({ duration: performanceNow() - previousStartTime, measurements: previousMeasurements || [], operations: previousOperations || [], treeSnapshot: registeredIDs.reduce((tree, id) => { var ownerID = ReactComponentTreeDevtool.getOwnerID(id); var parentID = ReactComponentTreeDevtool.getParentID(id); tree[id] = { displayName: ReactComponentTreeDevtool.getDisplayName(id), text: ReactComponentTreeDevtool.getText(id), updateCount: ReactComponentTreeDevtool.getUpdateCount(id), childIDs: ReactComponentTreeDevtool.getChildIDs(id), // Text nodes don't have owners but this is close enough. ownerID: ownerID || ReactComponentTreeDevtool.getOwnerID(parentID), parentID, }; return tree; }, {}), }); } currentFlushStartTime = performanceNow(); currentFlushMeasurements = []; ReactComponentTreeDevtool.purgeUnmountedComponents(); ReactNativeOperationHistoryDevtool.clearHistory(); } }
function pauseCurrentLifeCycleTimer() { var currentTimer = { startTime: currentTimerStartTime, nestedFlushStartTime: performanceNow(), debugID: currentTimerDebugID, timerType: currentTimerType, }; lifeCycleTimerStack.push(currentTimer); currentTimerStartTime = null; currentTimerNestedFlushDuration = null; currentTimerDebugID = null; currentTimerType = null; }
const queryCallback = (id: number, pendingQuery, error, results) => { const time = performanceNow() - initTime; const name = pendingQuery.getDebugName(); console.timeStamp(`← END: Relay query ${id} ${name}`); console.groupCollapsed( `%cRelay query ${id} ${time / 1000} ${name}`, `color:${error ? 'red' : 'black'};` ); console.timeEnd(id); const query = pendingQuery.getQueryString(); console.debug( '%c%s\n', 'font-size:10px; color:#333; font-family:mplus-2m-regular,menlo,' + 'monospaced;', query ); error && console.error(error); results && console.log(results); console.groupEnd(); };
function beginLifeCycleTimer(debugID, timerType) { if (currentFlushNesting === 0) { return; } if (currentTimerType && !lifeCycleTimerHasWarned) { warning( false, 'There is an internal error in the React performance measurement code. ' + 'Did not expect %s timer to start while %s timer is still in ' + 'progress for %s instance.', timerType, currentTimerType || 'no', (debugID === currentTimerDebugID) ? 'the same' : 'another' ); lifeCycleTimerHasWarned = true; } currentTimerStartTime = performanceNow(); currentTimerNestedFlushDuration = 0; currentTimerDebugID = debugID; currentTimerType = timerType; }
callTimer: function(timerID) { warning(timerID <= JSTimersExecution.GUID, 'Tried to call timer with ID ' + timerID + ' but no such timer exists'); var timerIndex = JSTimersExecution.timerIDs.indexOf(timerID); // timerIndex of -1 means that no timer with that ID exists. There are // two situations when this happens, when a garbage timer ID was given // and when a previously existing timer was deleted before this callback // fired. In both cases we want to ignore the timer id, but in the former // case we warn as well. if (timerIndex === -1) { return; } var type = JSTimersExecution.types[timerIndex]; var callback = JSTimersExecution.callbacks[timerIndex]; // Clear the metadata if (type === JSTimersExecution.Type.setTimeout || type === JSTimersExecution.Type.setImmediate || type === JSTimersExecution.Type.requestAnimationFrame) { JSTimersExecution._clearIndex(timerIndex); } try { if (type === JSTimersExecution.Type.setTimeout || type === JSTimersExecution.Type.setInterval || type === JSTimersExecution.Type.setImmediate) { callback(); } else if (type === JSTimersExecution.Type.requestAnimationFrame) { var currentTime = performanceNow(); callback(currentTime); } else { console.error('Tried to call a callback with invalid type: ' + type); return; } } catch (e) { // Don't rethrow so that we can run every other timer. JSTimersExecution.errors = JSTimersExecution.errors || []; JSTimersExecution.errors.push(e); } },
function markEnd(debugID, markType) { if (!shouldMark(debugID)) { return; } var markName = `${debugID}::${markType}`; var displayName = ReactComponentTreeHook.getDisplayName(debugID) || 'Unknown'; // Chrome has an issue of dropping markers recorded too fast: // https://bugs.chromium.org/p/chromium/issues/detail?id=640652 // To work around this, we will not report very small measurements. // I determined the magic number by tweaking it back and forth. // 0.05ms was enough to prevent the issue, but I set it to 0.1ms to be safe. // When the bug is fixed, we can `measure()` unconditionally if we want to. var timeStamp = performanceNow(); if (timeStamp - lastMarkTimeStamp > 0.1) { var measurementName = `${displayName} [${markType}]`; performance.measure(measurementName, markName); } performance.clearMarks(markName); performance.clearMeasures(measurementName); }
emitEvent('onEndFlush'); }, onBeginLifeCycleTimer(debugID, timerType) { emitEvent('onBeginLifeCycleTimer', debugID, timerType); if (__DEV__) { if (isProfiling && currentFlushNesting > 0) { warning( !currentTimerType, 'There is an internal error in the React performance measurement code. ' + 'Did not expect %s timer to start while %s timer is still in ' + 'progress for %s instance.', timerType, currentTimerType || 'no', (debugID === currentTimerDebugID) ? 'the same' : 'another' ); currentTimerStartTime = performanceNow(); currentTimerDebugID = debugID; currentTimerType = timerType; } } }, onEndLifeCycleTimer(debugID, timerType) { if (__DEV__) { if (isProfiling && currentFlushNesting > 0) { warning( currentTimerType === timerType, 'There is an internal error in the React performance measurement code. ' + 'We did not expect %s timer to stop while %s timer is still in ' + 'progress for %s instance. Please report this as a bug in React.', timerType, currentTimerType || 'no',
* Copyright (c) 2013-present, 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 generateClientID * @typechecks */ 'use strict'; const crc32 = require('crc32'); const performanceNow = require('performanceNow'); let _clientID = 1; const _prefix = 'client:' + crc32('' + performanceNow()); /** * Generate a unique clientID for GraphQL data objects that do not already have * an ID or their ID = null * * @internal */ function generateClientID() { return _prefix + _clientID++; } module.exports = generateClientID;
function burnCPU(milliseconds) { const start = performanceNow(); while (performanceNow() < (start + milliseconds)) {} }
componentDidMount() { const timeToMount = performanceNow() - this.state.ctorTimestamp; this.setState({timeToMount}); totalWidgets++; }
return function(...args) { var totalTime; var rv; var start; if (fnName === '_renderNewRootComponent' || fnName === 'flushBatchedUpdates') { // A "measurement" is a set of metrics recorded for each flush. We want // to group the metrics for a given flush together so we can look at the // components that rendered and the DOM operations that actually // happened to determine the amount of "wasted work" performed. ReactDefaultPerf._allMeasurements.push({ exclusive: {}, inclusive: {}, render: {}, counts: {}, writes: {}, displayNames: {}, totalTime: 0 }); start = performanceNow(); rv = func.apply(this, args); ReactDefaultPerf._allMeasurements[ ReactDefaultPerf._allMeasurements.length - 1 ].totalTime = performanceNow() - start; return rv; } else if (moduleName === 'ReactDOMIDOperations' || moduleName === 'ReactComponentBrowserEnvironment') { start = performanceNow(); rv = func.apply(this, args); totalTime = performanceNow() - start; if (fnName === '_mountImageIntoNode') { var mountID = ReactMount.getID(args[1]); ReactDefaultPerf._recordWrite(mountID, fnName, totalTime, args[0]); } else if (fnName === 'dangerouslyProcessChildrenUpdates') { // special format args[0].forEach(function(update) { var writeArgs = {}; if (update.fromIndex !== null) { writeArgs.fromIndex = update.fromIndex; } if (update.toIndex !== null) { writeArgs.toIndex = update.toIndex; } if (update.textContent !== null) { writeArgs.textContent = update.textContent; } if (update.markupIndex !== null) { writeArgs.markup = args[1][update.markupIndex]; } ReactDefaultPerf._recordWrite( update.parentID, update.type, totalTime, writeArgs ); }); } else { // basic format ReactDefaultPerf._recordWrite( args[0], fnName, totalTime, Array.prototype.slice.call(args, 1) ); } return rv; } else if (moduleName === 'ReactCompositeComponent' && ( fnName === 'mountComponent' || fnName === 'updateComponent' || // TODO: receiveComponent()? fnName === '_renderValidatedComponent')) { var rootNodeID = fnName === 'mountComponent' ? args[0] : this._rootNodeID; var isRender = fnName === '_renderValidatedComponent'; var isMount = fnName === 'mountComponent'; var mountStack = ReactDefaultPerf._mountStack; var entry = ReactDefaultPerf._allMeasurements[ ReactDefaultPerf._allMeasurements.length - 1 ]; if (isRender) { addValue(entry.counts, rootNodeID, 1); } else if (isMount) { mountStack.push(0); } start = performanceNow(); rv = func.apply(this, args); totalTime = performanceNow() - start; if (isRender) { addValue(entry.render, rootNodeID, totalTime); } else if (isMount) { var subMountTime = mountStack.pop(); mountStack[mountStack.length - 1] += totalTime; addValue(entry.exclusive, rootNodeID, totalTime - subMountTime); addValue(entry.inclusive, rootNodeID, totalTime); } else { addValue(entry.inclusive, rootNodeID, totalTime); } entry.displayNames[rootNodeID] = { current: typeof this._currentElement.type === 'string' ? this._currentElement.type : this.getName(), owner: this._currentElement._owner ? this._currentElement._owner.getName() : '<root>' }; return rv; } else { return func.apply(this, args); } };
* @typechecks * @flow */ 'use strict'; import type RelayMutationRequest from 'RelayMutationRequest'; const Relay = require('RelayPublic'); import type RelayQueryRequest from 'RelayQueryRequest'; import type {NetworkLayer} from 'RelayTypes'; const performanceNow = require('performanceNow'); const RelayNetworkDebug = { init(networkLayer: NetworkLayer): void { const initTime = performanceNow(); const queryCallback = (id: number, pendingQuery, error, results) => { const time = performanceNow() - initTime; const name = pendingQuery.getDebugName(); console.timeStamp(`← END: Relay query ${id} ${name}`); console.groupCollapsed( `%cRelay query ${id} ${time / 1000} ${name}`, `color:${error ? 'red' : 'black'};` ); console.timeEnd(id); const query = pendingQuery.getQueryString(); console.debug( '%c%s\n', 'font-size:10px; color:#333; font-family:mplus-2m-regular,menlo,' + 'monospaced;',