Skip to content

Profiling and Performance

Nicole edited this page Mar 7, 2018 · 4 revisions

Chrome’s browser performance tools are oft cited in the literature (read: medium articles and blog posts) as a main choice for profiling react projects to determine performance bottlenecks. To perform this profiling in your Chrome browser, follow these steps.

  1. Build our application in a development environment. For FluxNotes, this can be done by running the application with yarn start.
  2. Visit the FullApp webpage in your browser, but append the ?react_perf query to the end of the url. Using the default configuration of our development build, this would mean visiting http://localhost:3000/demo1?react_perf.
  3. Open ‘Developer Tools’ in your browser by right clicking anywhere and selecting “Inspect”, by going to browser settings menu in the top-right hand corner of the browser, selecting “More tools”, selecting “Developer Tools”, or typing Ctrl + Shift + I.
  4. It is recommended that you change the “Dock Side” settings of the dev-tools panel by clicking the three dots in the upper-right hand corner of the dev-tools panel, and selecting the “Undock to separate window” option.
  5. Select the “Performance” tab at the top of the dev-tools window panel.
  6. Either type Ctrl + E or the round button at the top-left side of the dev-tools panel to begin recording activity in the application.
  7. Perform whatever actions you’d like to profile.
  8. Hit stop when done.
  9. Wait for the results of your profiling to load.
  10. Select the “User-Timing” section in the activity breakdown below the timelines view of application activity. N.B. this will only be available if the ?react_perf query is added to the end of the url.
  11. Investigate what functions and Components are responsible for the majority of application runtime.

v1: 03/01/2018

Profiling

Investigations in chrome’s browser performance tools highlighted visualizers as our biggest pain-point, rendered in TargetedDataSubpanel. By highlighting the User Timing events occurring during keypresses, one can see that much of the time taken up by our application is consumed by TargetedDataSubPanel and its individual visualizers. It seems that, with each keypress, our visualizers are updating even if the data they render hasn’t been updated.

Root Cause

On inspection, each visualizer re-renders with every keystroke in our editor. This was confirmed by removing the visualizers from the application and entering text identical to that of the test case; performance improved such that equivalent operations complete twice as quickly.

Documentation on react optimizations show that react components always update by default. This behavior can be overridden by a) defining a ‘shouldComponentUpdate’ function to decide, based on ‘nextProps’ and ‘nextState’, whether the component should update, or b) redefine the component class as an extension of ‘React.PureComponent’ instead of ‘React.Component’, which is a component that does a check on all of its expected props/state with the individual values of each prop/state value.

Both of these solutions do nothing to optimize our TargetedDataSubpanel. This is because the prop that this component and all subservient components care about, ‘patient’, is an object that we mutate, never assigning it a new value. Because of this, any updates to the patient object are reflected in the ‘nextProps’ and in the current value of ‘this.props’; they are both references to the same object, and therefore both reflect the mutations. To fix this performance issue, I see two immediate options.

  1. We can change the way we handle updates to the patient to return a new patient object every time. This will require changes to any functions that update their props-given patient object (e.g. in our shortcut objects, in our metadata, possibly to our dataAccess layer), FullApp and how it handles updates to the source patient object
  2. We can maintain a copy of the patient prop local to the components that need checking. This would allow components like TargetedDataPanel or its children components to maintain their own history of the patient which they would compare against.

Once we’ve done these changes, we can continue profiling and working on new bottlenecks down the line.

Related Pages:

Clone this wiki locally