@samitouri / QOS-React / commits / 3e82e4152e

Added getInteractions message

Brian Vaughn committed Mar 19, 2019 at 18:13 UTC 3e82e4152e7a6c1646261f8952b9ac34f5e86bc0
6 files changed +133 -11
OVERVIEW.md
+4
@@ -268,10 +268,12 @@ Here is an example commit in which two elements were rendered and one interactio
268 commitIndex: 0,
269 interactions: [
270 {
271 + id: 8,
272 timestamp: 4,
273 name: "Foo"
274 },
275 {
276 + id: 11,
277 timestamp: 4,
278 name: "Bar"
279 }
@@ -332,6 +334,7 @@ Here is an example of a profiling session consisting of two interactions:
334 rootID: 1,
335 interactions: [
336 {
337 + id: 8,
338 name: "Foo",
339 timestamp: 4,
340 commits: [
@@ -340,6 +343,7 @@ Here is an example of a profiling session consisting of two interactions:
343 ]
344 },
345 {
346 + id: 11,
347 name: "Bar",
348 timestamp: 4,
349 commits: [
src/backend/agent.js
+21
@@ -50,6 +50,7 @@ export default class Agent extends EventEmitter {
50 // TODO (profiling) Interactions
51
52 bridge.addListener('getCommitDetails', this.getCommitDetails);
53 + bridge.addListener('getInteractions', this.getInteractions);
54 bridge.addListener('getProfilingStatus', this.getProfilingStatus);
55 bridge.addListener('getProfilingSummary', this.getProfilingSummary);
56 bridge.addListener('highlightElementInDOM', this.highlightElementInDOM);
@@ -100,6 +101,26 @@ export default class Agent extends EventEmitter {
101 }
102 };
103
104 + getInteractions = ({
105 + commitIndex,
106 + rendererID,
107 + rootID,
108 + }: {
109 + commitIndex: number,
110 + rendererID: number,
111 + rootID: number,
112 + }) => {
113 + const renderer = this._rendererInterfaces[rendererID];
114 + if (renderer == null) {
115 + console.warn(`Invalid renderer id "${rendererID}"`);
116 + } else {
117 + this._bridge.send(
118 + 'interactions',
119 + renderer.getInteractions(rootID, commitIndex)
120 + );
121 + }
122 + };
123 +
124 getProfilingStatus = () => {
125 this._bridge.send('profilingStatus', this._isProfiling);
126 };
src/backend/renderer.js
+38 -9
@@ -30,6 +30,8 @@ import type {
30 Fiber,
31 FiberData,
32 Interaction,
33 + Interactions,
34 + InteractionWithCommits,
35 ProfilingSummary,
36 ReactRenderer,
37 RendererInterface,
@@ -476,10 +478,6 @@ export function attach(
478 // When a mount or update is in progress, this value tracks the root that is being operated on.
479 let currentRootID: number = -1;
480
479 - function getInteractionID({ name, timestamp }: Interaction): string {
480 - return `${timestamp}-${name}`;
481 - }
482 -
481 function getFiberID(primaryFiber: Fiber): number {
482 if (!fiberToIDMap.has(primaryFiber)) {
483 const id = getUID();
@@ -894,11 +892,7 @@ export function attach(
892 actualDurations: [],
893 commitTime: performance.now() - profilingStartTime,
894 interactions: Array.from(root.memoizedInteractions).map(
897 - (interaction: Interaction) => ({
898 - id: getInteractionID(interaction),
899 - name: interaction.name,
900 - timestamp: interaction.timestamp - profilingStartTime,
901 - })
895 + (interaction: Interaction) => ({ ...interaction })
896 ),
897 maxActualDuration: 0,
898 };
@@ -1431,6 +1425,40 @@ export function attach(
1425 };
1426 }
1427
1428 + function getInteractions(rootID: number, commitIndex: number): Interactions {
1429 + const commitProfilingMetadata = ((rootToCommitProfilingMetadataMap: any): CommitProfilingMetadataMap).get(
1430 + rootID
1431 + );
1432 + if (commitProfilingMetadata != null) {
1433 + const interactionsMap: Map<number, InteractionWithCommits> = new Map();
1434 +
1435 + commitProfilingMetadata.forEach((commitProfilingData, commitIndex) => {
1436 + commitProfilingData.interactions.forEach(interaction => {
1437 + const interactionWithCommits = interactionsMap.get(interaction.id);
1438 + if (interactionWithCommits != null) {
1439 + interactionWithCommits.commits.push(commitIndex);
1440 + } else {
1441 + interactionsMap.set(interaction.id, {
1442 + ...interaction,
1443 + commits: [commitIndex],
1444 + });
1445 + }
1446 + });
1447 + });
1448 +
1449 + return {
1450 + interactions: Array.from(interactionsMap.values()),
1451 + rootID,
1452 + };
1453 + }
1454 +
1455 + // TODO (profiling) Is this right? Should I return null? Does it matter?
1456 + return {
1457 + interactions: [],
1458 + rootID,
1459 + };
1460 + }
1461 +
1462 function getProfilingSummary(rootID: number): ProfilingSummary {
1463 const interactions = new Set();
1464 const commitDurations = [];
@@ -1492,6 +1520,7 @@ export function attach(
1520 cleanup,
1521 getCommitDetails,
1522 getFiberIDFromNative,
1523 + getInteractions,
1524 getNativeFromReactElement,
1525 getProfilingSummary,
1526 handleCommitFiberRoot,
src/backend/types.js
+12 -1
@@ -50,7 +50,7 @@ export type ReactRenderer = {
50 };
51
52 export type Interaction = {|
53 - id: string,
53 + id: number,
54 name: string,
55 timestamp: number,
56 |};
@@ -62,6 +62,16 @@ export type CommitDetails = {|
62 rootID: number,
63 |};
64
65 +export type InteractionWithCommits = {|
66 + ...Interaction,
67 + commits: Array<number>,
68 +|};
69 +
70 +export type Interactions = {|
71 + interactions: Array<InteractionWithCommits>,
72 + rootID: number,
73 +|};
74 +
75 export type ProfilingSummary = {|
76 commitDurations: Array<number>,
77 commitTimes: Array<number>,
@@ -78,6 +88,7 @@ export type RendererInterface = {
88 component: NativeType,
89 findNearestUnfilteredAncestor?: boolean
90 ) => number | null,
91 + getInteractions: (rootID: number, commitIndex: number) => Interactions,
92 getProfilingSummary: (rootID: number) => ProfilingSummary,
93 handleCommitFiberRoot: (fiber: Object) => void,
94 handleCommitFiberUnmount: (fiber: Object) => void,
src/devtools/ProfilingCache.js
+49
@@ -19,10 +19,12 @@ import type { Resource } from './cache';
19 import type { Bridge } from '../types';
20 import type {
21 CommitDetails as CommitDetailsBackend,
22 + Interactions as InteractionsBackend,
23 ProfilingSummary as ProfilingSummaryBackend,
24 } from 'src/backend/types';
25 import type {
26 CommitDetails as CommitDetailsFrontend,
27 + Interactions as InteractionsFrontend,
28 CommitTree as CommitTreeFrontend,
29 ProfilingSummary as ProfilingSummaryFrontend,
30 } from 'src/devtools/views/Profiler/types';
@@ -35,6 +37,11 @@ type CommitDetailsParams = {|
37 rendererID: number,
38 |};
39
40 +type InteractionsParams = {|
41 + rootID: number,
42 + rendererID: number,
43 +|};
44 +
45 type GetCommitTreeParams = {|
46 commitIndex: number,
47 profilingSummary: ProfilingSummaryFrontend,
@@ -56,6 +63,11 @@ export default class ProfilingCache {
63 (commitDetails: CommitDetailsFrontend) => void
64 > = new Map();
65
66 + _pendingInteractionsMap: Map<
67 + number,
68 + (interactions: InteractionsFrontend) => void
69 + > = new Map();
70 +
71 _pendingProfileSummaryMap: Map<
72 number,
73 (profilingSummary: ProfilingSummaryFrontend) => void
@@ -90,6 +102,30 @@ export default class ProfilingCache {
102 `${rootID}-${commitIndex}`
103 );
104
105 + Interactions: Resource<
106 + InteractionsParams,
107 + InteractionsFrontend
108 + > = createResource(
109 + ({ rendererID, rootID }: InteractionsParams) => {
110 + return new Promise(resolve => {
111 + if (!this._store.profilingOperations.has(rootID)) {
112 + // If no profiling data was recorded for this root, skip the round trip.
113 + resolve({
114 + interactions: [],
115 + rootID,
116 + });
117 + } else {
118 + this._pendingInteractionsMap.set(rootID, resolve);
119 + this._bridge.send('getInteractions', {
120 + rendererID,
121 + rootID,
122 + });
123 + }
124 + });
125 + },
126 + ({ rendererID, rootID }: ProfilingSummaryParams) => rootID
127 + );
128 +
129 ProfilingSummary: Resource<
130 ProfilingSummaryParams,
131 ProfilingSummaryFrontend
@@ -118,6 +154,7 @@ export default class ProfilingCache {
154 this._store = store;
155
156 bridge.addListener('commitDetails', this.onCommitDetails);
157 + bridge.addListener('interactions', this.onInteractions);
158 bridge.addListener('profilingSummary', this.onProfileSummary);
159 }
160
@@ -207,6 +244,18 @@ export default class ProfilingCache {
244 }
245 };
246
247 + onInteractions = ({ interactions, rootID }: InteractionsBackend) => {
248 + const resolve = this._pendingInteractionsMap.get(rootID);
249 + if (resolve != null) {
250 + this._pendingInteractionsMap.delete(rootID);
251 +
252 + resolve({
253 + interactions,
254 + rootID,
255 + });
256 + }
257 + };
258 +
259 onProfileSummary = ({
260 commitDurations,
261 commitTimes,
src/devtools/views/Profiler/types.js
+9 -1
@@ -15,11 +15,19 @@ export type CommitTree = {|
15 |};
16
17 export type Interaction = {|
18 - id: string,
18 + id: number,
19 name: string,
20 timestamp: number,
21 |};
22
23 +export type Interactions = {|
24 + interactions: Array<{|
25 + ...Interaction,
26 + commits: Array<number>,
27 + |}>,
28 + rootID: number,
29 +|};
30 +
31 export type CommitDetails = {|
32 actualDurations: Map<number, number>,
33 interactions: Array<Interaction>,