farmdev

Profiling And Optimizing React Apps

At Mozilla, the Add-ons team hosts a casual show & tell each month. It's a public meeting and we invite community members to share their work.

This time I demo'd some of the work I've been doing to profile and optimize our code manager, a tool that the review team uses to make sure add-ons are safe for Firefox users. It's a code viewer that looks like an IDE: a file list on the left, code in the middle, and a file overview on the right. The UX is similar to reviewing a pull request on GitHub but the main difference is we integrate our automated scanning tools to provide hints about potential problems.

Watch the demo.

The big challenge we ran into is how to display very large code files and diffs without lag. Large files show up in add-ons occasionally. Developers sometimes use transpilers such as Webpack even though they aren't strictly necessary for add-ons. Developers sometimes create long code files because, well, that's what happens when you write code.

The demo shows me working with User Timing data (as documented) to get a general grasp on which React components are responsible for the slowdown. After finding the slow component, I inspect the actual function calls and the profiler reveals some low hanging fruit instantly. In some cases I was able to change only a few lines of code to reduce execution time by as much as 99%.

This profiling technique is a great way to validate assumptions and find real problems rather than trying to optimize based on intuition. As is usually the case, I was surprised by some of the functions that were slowing down the rendering of large files.

If I had infinite time I would have rewritten the code view using a sliding window with dynamic scrolling so that only the visible lines of code were getting inserted into the DOM but we have an ambitious road map and a small team! I was able to find enough quick wins to make large files viewable but I'm hoping we'll soon have time to improve it further.

You may notice that I'm using a development build to do my profiling. This isn't great because it contains overhead from our dev environment and any overhead can be misleading when profiling. I needed a development build of React to get the User Timing data, despite this Webpack aliasing hack (I just couldn't get it to work, to be honest). For my specific case, I switched to a production build once I had a grasp on where the slowness was. This helped me measure the actual impact of my optimizations.