Skip to content

Commit e15a0c6

Browse files
authored
Merge pull request #13 from oslabs-beta/performanceTab
Performance tab
2 parents 39e2055 + 3c251a1 commit e15a0c6

File tree

8 files changed

+288
-47
lines changed

8 files changed

+288
-47
lines changed

src/app/components/LinkControls.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { List } from '@material-ui/core';
22
import React from 'react';
3+
import snapshots from './snapshots';
34
// Font size of the Controls label and Dropdowns
45
const controlStyles = {
56
fontSize: '12px',
@@ -34,6 +35,7 @@ const nodeList = [];
3435

3536
const collectNodes = (node) => {
3637
// console.log("This is the root node", node);
38+
// console.log('this is nodelist', nodeList)
3739
nodeList.splice(0, nodeList.length); { /* We used the .splice method here to ensure that nodeList did not accumulate with page refreshes */ }
3840
nodeList.push(node);
3941
for (let i = 0; i < nodeList.length; i++) {
@@ -60,7 +62,7 @@ export default function LinkControls({
6062
setSelectedNode,
6163
snapShots,
6264
}: Props) {
63-
65+
// console.log('this is line 64', snapShots)
6466
collectNodes(snapShots);
6567

6668
return (

src/app/components/PerformanceVisx.tsx

Lines changed: 138 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* eslint-disable guard-for-in */
2+
/* eslint-disable no-restricted-syntax */
13
// @ts-nocheck
24
import React, { useState } from 'react';
35
import FormControlLabel from '@material-ui/core/FormControlLabel';
@@ -8,11 +10,17 @@ import {
810
NavLink,
911
Switch,
1012
} from 'react-router-dom';
13+
import { Component } from 'react';
14+
import { render } from 'react-dom';
1115
import RenderingFrequency from './RenderingFrequency';
1216
// import Switch from '@material-ui/core/Switch';
1317
import BarGraph from './BarGraph';
1418
import BarGraphComparison from './BarGraphComparison';
1519
import { useStoreContext } from '../store';
20+
// import snapshots from './snapshots';
21+
import snapshots from './snapshots';
22+
23+
const exclude = ['childExpirationTime', 'staticContext', '_debugSource', 'actualDuration', 'actualStartTime', 'treeBaseDuration', '_debugID', '_debugIsCurrentlyTiming', 'selfBaseDuration', 'expirationTime', 'effectTag', 'alternate', '_owner', '_store', 'get key', 'ref', '_self', '_source', 'firstBaseUpdate', 'updateQueue', 'lastBaseUpdate', 'shared', 'responders', 'pending', 'lanes', 'childLanes', 'effects', 'memoizedState', 'pendingProps', 'lastEffect', 'firstEffect', 'tag', 'baseState', 'baseQueue', 'dependencies', 'Consumer', 'context', '_currentRenderer', '_currentRenderer2', 'mode', 'flags', 'nextEffect', 'sibling', 'create', 'deps', 'next', 'destroy', 'parentSub', 'child', 'key', 'return', 'children', '$$typeof', '_threadCount', '_calculateChangedBits', '_currentValue', '_currentValue2', 'Provider', '_context', 'stateNode', 'elementType', 'type'];
1624

1725
/* NOTES
1826
Issue - Not fully compatible with recoil apps. Reference the recoil-todo-test.
@@ -32,8 +40,123 @@ interface BarStackProps {
3240
hierarchy: any;
3341
}
3442

43+
// function getComponentsArr(componentName, snapshots, node) {
44+
// //Input: Name of component and all snapshots
45+
// //Output: One array of each individual snapshot
46+
47+
// //NOTE:
48+
// //Every snapshot is an object with a children array with a snapshot that also has a children array etc
49+
// //Children arrays more than one signify siblings
50+
51+
// }
52+
// // snapshots.map(rootNode => {
53+
// // // rootNode.name
54+
// // let currNode = rootNode
55+
// // while (currNode) {
56+
// // if (currNode.name === componentName) {
57+
// // return currNode.componentData.props
58+
// // } else {
59+
// // currNode = currNode.children[0]
60+
// // currNode = currNode.children[1]
61+
// // }
62+
// // }
63+
// // })
64+
const makePropsPretty = data => {
65+
const propsFormat = [];
66+
const nestedObj = [];
67+
// console.log('show me the data we are getting', data);
68+
if (typeof data !== 'object') {
69+
return <p>{data}</p>;
70+
}
71+
for (const key in data) {
72+
if (data[key] !== 'reactFiber' && typeof data[key] !== 'object' && exclude.includes(key) !== true) {
73+
propsFormat.push(<p className="stateprops">
74+
{`${key}: ${data[key]}`}
75+
</p>);
76+
} else if (data[key] !== 'reactFiber' && typeof data[key] === 'object' && exclude.includes(key) !== true) {
77+
const result = makePropsPretty(data[key]);
78+
nestedObj.push(result);
79+
}
80+
}
81+
if (nestedObj) {
82+
propsFormat.push(nestedObj);
83+
}
84+
// console.log('this is propsformat', propsFormat);
85+
return propsFormat;
86+
};
87+
88+
const collectNodes = (snaps, componentName) => {
89+
const componentsResult = [];
90+
const renderResult = [];
91+
let trackChanges = 0;
92+
let newChange = true;
93+
for (let x = 0; x < snaps.length; x++) {
94+
const snapshotList = [];
95+
snapshotList.push(snaps[x]);
96+
for (let i = 0; i < snapshotList.length; i++) {
97+
const cur = snapshotList[i];
98+
if (cur.name === componentName) {
99+
const renderTime = Number(
100+
Number.parseFloat(cur.componentData.actualDuration).toPrecision(5),
101+
);
102+
if (renderTime === 0) {
103+
break;
104+
} else {
105+
renderResult.push(renderTime);
106+
}
107+
console.log('show me the render time', renderTime);
108+
// compare the last pushed component Data from the array to the current one to see if there are differences
109+
if (x !== 0 && componentsResult.length !== 0) {
110+
// needs to be stringified because values are hard to determine if true or false if in they're seen as objects
111+
if (JSON.stringify(Object.values(componentsResult[newChange ? componentsResult.length - 1 : trackChanges])[0]) !== JSON.stringify(cur.componentData.props)) {
112+
newChange = true;
113+
// const props = { [`snapshot${x}`]: { rendertime: formatRenderTime(cur.componentData.actualDuration), ...cur.componentData.props } };
114+
const props = { [`snapshot${x}`]: { ...cur.componentData.props } };
115+
console.log('show me props structure', props)
116+
componentsResult.push(props);
117+
} else {
118+
newChange = false;
119+
trackChanges = componentsResult.length - 1;
120+
const props = { [`snapshot${x}`]: { state: 'Same state as prior snapshot' } };
121+
componentsResult.push(props);
122+
}
123+
} else {
124+
// const props = { [`snapshot${x}`]: { ...cur.componentData.props}};
125+
// props[`snapshot${x}`].rendertime = formatRenderTime(cur.componentData.actualDuration);
126+
const props = { [`snapshot${x}`]: { ...cur.componentData.props } };
127+
componentsResult.push(props);
128+
}
129+
break;
130+
}
131+
if (cur.children && cur.children.length > 0) {
132+
for (const child of cur.children) {
133+
snapshotList.push(child);
134+
}
135+
}
136+
}
137+
}
138+
// console.log('componentsResult looks like: ', componentsResult);
139+
140+
// console.log('we should be seeing react components with information', componentsResult);
141+
// componentsResult.push(renderResult);
142+
const finalResults = componentsResult.map((e, index) => {
143+
const name = Object.keys(e)[0];
144+
console.log('this is name', name, 'show me e', e);
145+
e[name].rendertime = renderResult[index];
146+
console.log('this is e', e);
147+
return e;
148+
});
149+
for (let i = 0; i < finalResults.length; i++) {
150+
for (const componentSnapshot in finalResults[i]) {
151+
finalResults[i][componentSnapshot] = makePropsPretty(finalResults[i][componentSnapshot]);
152+
}
153+
}
154+
console.log('finalresults', finalResults);
155+
return finalResults;
156+
};
157+
35158
/* DATA HANDLING HELPER FUNCTIONS */
36-
const traverse = (snapshot, data, currTotalRender = 0) => {
159+
const traverse = (snapshot, data, snapshots, currTotalRender = 0) => {
37160
if (!snapshot.children[0]) return;
38161

39162
// loop through snapshots
@@ -56,24 +179,26 @@ const traverse = (snapshot, data, currTotalRender = 0) => {
56179
renderFrequency: 0,
57180
totalRenderTime: 0,
58181
rtid: '',
182+
information: {},
59183
};
60184
if (child.state !== 'stateless') data.componentData[componentName].stateType = 'stateful';
61185
}
62186
// increment render frequencies
63187
if (renderTime > 0) {
64-
console.log('what is the child', child);
65-
console.log('por que?', data.componentData[componentName]);
188+
// console.log('what is the child', child);
189+
// console.log('por que?', data.componentData[componentName]);
66190
data.componentData[componentName].renderFrequency++;
67191
} else {
68-
console.log('what is the child', child);
69-
console.log('we dont increment here', data.componentData[componentName], 'and the child', child);
192+
// console.log('what is the child', child);
193+
// console.log('we dont increment here', data.componentData[componentName], 'and the child', child);
70194
}
71195

72196
// add to total render time
73197
data.componentData[componentName].totalRenderTime += renderTime;
74198
// Get rtid for the hovering feature
75199
data.componentData[componentName].rtid = child.rtid;
76-
traverse(snapshot.children[idx], data, currTotalRender);
200+
data.componentData[componentName].information = collectNodes(snapshots, child.name);
201+
traverse(snapshot.children[idx], data, snapshots, currTotalRender);
77202
});
78203
// reassigns total render time to max render time
79204
data.maxTotalRender = Math.max(currTotalRender, data.maxTotalRender);
@@ -85,13 +210,13 @@ const allStorage = () => {
85210
const values = [];
86211
const keys = Object.keys(localStorage);
87212
let i = keys.length;
88-
console.log('allstorage keys', keys);
213+
// console.log('allstorage keys', keys);
89214

90215
while (i--) {
91216
const series = localStorage.getItem(keys[i]);
92217
values.push(JSON.parse(series));
93218
}
94-
console.log('allstorage values', values);
219+
// console.log('allstorage values', values);
95220
return values;
96221
};
97222

@@ -113,10 +238,10 @@ const getPerfMetrics = (snapshots, snapshotsIds): {} => {
113238
componentData: {},
114239
maxTotalRender: 0,
115240
};
116-
console.log('show me all of the snapshots', snapshots);
241+
// console.log('show me all of the snapshots', snapshots);
117242
snapshots.forEach((snapshot, i) => {
118243
perfData.barStack.push({ snapshotId: snapshotsIds[i] });
119-
traverse(snapshot, perfData);
244+
traverse(snapshot, perfData, snapshots);
120245
});
121246
return perfData;
122247
};
@@ -133,6 +258,7 @@ const PerformanceVisx = (props: BarStackProps) => {
133258
const [comparisonData, setComparisonData] = useState();
134259
const NO_STATE_MSG = 'No state change detected. Trigger an event to change state';
135260
const data = getPerfMetrics(snapshots, getSnapshotIds(hierarchy));
261+
// console.log('this is line 220', data);
136262

137263
const renderComparisonBargraph = () => {
138264
if (hierarchy) {
@@ -154,7 +280,9 @@ const PerformanceVisx = (props: BarStackProps) => {
154280
};
155281

156282
const renderComponentDetailsView = () => {
283+
// console.log('this is the info for rendering frequency', data.componentData);
157284
if (hierarchy) {
285+
// console.log('this is line 246', data.comparisonData);
158286
return <RenderingFrequency data={data.componentData} />;
159287
}
160288
return <div className="noState">{NO_STATE_MSG}</div>;

src/app/components/RenderingFrequency.tsx

Lines changed: 84 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,122 @@
1-
import React from 'react';
1+
/* eslint-disable jsx-a11y/click-events-have-key-events */
2+
/* eslint-disable jsx-a11y/no-static-element-interactions */
3+
/* eslint-disable react/prop-types */
4+
import React, { useState } from 'react';
5+
import { render } from 'react-dom';
26
import { onHover, onHoverExit } from '../actions/actions';
37
import { useStoreContext } from '../store';
48

5-
const RenderingFrequency = (props) => {
9+
const RenderingFrequency = props => {
610
const perfData = props.data;
711
return (
812
<div>
9-
{Object.keys(perfData).map((componentName) => {
13+
{Object.keys(perfData).map(componentName => {
1014
const currentComponent = perfData[componentName];
1115
return (
1216
<ComponentCard
1317
componentName={componentName}
1418
stateType={currentComponent.stateType}
1519
averageRenderTime={(
16-
currentComponent.totalRenderTime /
17-
currentComponent.renderFrequency
20+
currentComponent.totalRenderTime
21+
/ currentComponent.renderFrequency
1822
).toFixed(3)}
1923
renderFrequency={currentComponent.renderFrequency}
2024
rtid={currentComponent.rtid}
25+
information={perfData[componentName].information}
2126
/>
2227
);
2328
})}
2429
</div>
2530
);
2631
};
2732

28-
const ComponentCard = (props) => {
33+
const ComponentCard = props => {
2934
const {
3035
componentName,
3136
stateType,
3237
averageRenderTime,
3338
renderFrequency,
3439
rtid,
40+
information,
3541
} = props;
3642
const [{ tabs, currentTab }, dispatch] = useStoreContext();
43+
const [expand, setExpand] = useState(false);
3744

38-
const onMouseMove = () => {
39-
dispatch(onHover(rtid));
40-
};
41-
const onMouseLeave = () => {
42-
dispatch(onHoverExit(rtid));
43-
};
45+
// const onMouseMove = () => {
46+
// console.log(rtid);
47+
// dispatch(onHover(rtid));
48+
// };
49+
// const onMouseLeave = () => {
50+
// console.log(rtid);
51+
// dispatch(onHoverExit(rtid));
52+
// };
53+
54+
// render time for each component from each snapshot
55+
// differences in state change that happened prior;
56+
57+
58+
const dataComponentArray = [];
59+
for (let i = 0; i < information.length; i++) {
60+
dataComponentArray.push(<DataComponent header={Object.keys(information[i])} paragraphs={Object.values(information[i])} />);
61+
}
4462

4563
return (
46-
<div
47-
onMouseLeave={onMouseLeave}
48-
onMouseMove={onMouseMove}
49-
className="StyledGridElement"
50-
>
51-
<div className="RenderLeft">
52-
<h3>{componentName} </h3>
53-
<h4>{stateType}</h4>
54-
<h4>average time: {averageRenderTime} ms</h4>
64+
<div className="borderStyling">
65+
<div
66+
className={expand ? 'ExpandStyledGridElement' : 'StyledGridElement'}
67+
>
68+
<div className="RenderLeft">
69+
<h3>
70+
{componentName}
71+
{' '}
72+
</h3>
73+
<h4>{stateType}</h4>
74+
<h4>
75+
average time:
76+
{' '}
77+
{averageRenderTime}
78+
{' '}
79+
ms
80+
</h4>
81+
</div>
82+
<div
83+
onClick={() => {
84+
if (expand === true) {
85+
setExpand(false);
86+
} else {
87+
setExpand(true);
88+
}
89+
}}
90+
className="RenderRight"
91+
>
92+
<p>{renderFrequency}</p>
93+
</div>
5594
</div>
56-
<div className="RenderRight">
57-
<p>{renderFrequency}</p>
95+
<div className="DataComponent">
96+
{expand === true ? dataComponentArray : null}
5897
</div>
98+
99+
</div>
100+
);
101+
};
102+
103+
const DataComponent = props => {
104+
const {
105+
header,
106+
paragraphs,
107+
} = props;
108+
109+
// const [{ tabs, currentTab }, dispatch] = useStoreContext();
110+
return (
111+
<div>
112+
<h4>
113+
{' '}
114+
{header}
115+
</h4>
116+
<p>
117+
{' '}
118+
{paragraphs}
119+
</p>
59120
</div>
60121
);
61122
};

0 commit comments

Comments
 (0)