# Identifying & Diagnosing Bottlenecks

When your application is not performing as you would like or expect, what can you do? What follows is my general approach to solving performance bottlenecks with a focus on React specific tools. There is an element of creativity to the process though so you should take this more as a guide and not something set in stone. You can start here but also try to find what works best for you. 

These are the six main steps I use to solve performance bottlenecks: 

* Describing the performance bottleneck
* Measuring the bottleneck
* Identifying the source
* Diagnosing the cause
* Generating possible solutions
* Selecting and implementing a solution

{width: "90%", caption: "Figure 1: Solving Bottlenecks Cycle"}
![Figure 1: Solving Bottlenecks Cycle](./images/bottleneck-process.png) 

As you can see in Figure 1, I use them in a cycle centered around measuring the bottleneck so that I'll be able to track my progress and know when I have eliminated the bottleneck. 

## Describing Performance Issues

The first step is to identify and qualify the bottleneck. You can start by asking "what are the symptoms?" and "what triggers them?". It's very important to dig in as much as possible at this stage and gather as much information as possible. Here are the questions I generally use to get you started: 

* What specifically is the issue? 
  * A lack of responsiveness?
  * Temporary jankiness?
  * What am I/the user being prevented from doing?
* When does the issue start?
* When does it finish?
* Is the intensity and/or duration variable or constant?
* Is it predictable? Does it always happen?
* Does it seem like anything triggers it?

You can start with trying to answer these questions or you can come up with your own. The only way to get good at it is practice as it's more an art than a science, at this stage. 

This stage might not seem that important or the answers might seem obvious but being thorough here can actually save you a lot of time later on. It's very easy to misunderstand a bottleneck and then begin your investigation in the wrong place, wasting valuable time, or even worse, crafting a solution to the wrong problem. 

## Measuring

Once you've described the performance issue in as much detail as you can it's time to move on to the next stage: measuring the issue. This stage is vital to the process. Do not skip this stage. The only way later on to ensure you've actually fixed the problem is to measure the problem to the best of your ability. The better you can quantify the issue the easier the rest of the process will be. This can be very challenging, especially with things that seem immeasurable, like UI jankiness but if you work at it there is generally a way to do. We will discuss a few techniques coming up. 

One technique I use is very simple: timing a section of code and logging the results to the console. Most modern browsers now support the [PerformanceNavigationTiming](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming) API which includes many tools to make this process easier but doing it without the API works too. I often start logging an expansive amount of my code and then moving my measurement locations in closer to each other until they have either isolated a section of code or eliminated a section of code from the possibilities. 

While the logging times can be very useful for some bottlenecks, they can also be more cumbersome for a lot of React bottlenecks because it can be a lot of work to insert your timing calls in the right location when the bottleneck appears to be coming from somewhere in a tree of React components. React provides a tool for this though: a profiler. A profiler is a tool, usually in conjunction with a compiler, that effectively inserts many timers all over your code and then compiles the results in to charts so it's easier to pinpoint issues. 

I> Profilers don't usually insert "timers" instead using sampling or other techniques but the important part for us here is just knowing that they can provide insight into the performance of your program and that they can have an effect on performance themselves.

To use the React profiler you will first need to ensure that you have installed the React developer tools plugin for the browser you are using. After that you must ensure your build is `instrumented` (meaning it is setup for use with the profiler). With create-react-app this will be when in development mode. If you are unsure check out the documentation for the React profiler as well as your build tools, like webpack. 


