LogoTRUONG PHAM
Home
Projects
Blogs
YouTube
Contact

Newsletter

Stay updated with technical artifacts and engineering insights.

LogoTRUONG PHAM

Building scalable software and sharing insights on technology & life.

Sitemap

  • Home
  • Projects
  • Blogs
  • YouTube
  • Contact

Connect

  • GitHub
  • LinkedIn
  • Email
  • YouTube

© 2024 TRUONG PHAM. © All rights reserved.

Privacy PolicyTerms of Service
Back
Blog #19: Chrome Performance Tab – Looking through a microscope at the system's pulse
50 FRONTEND LESSONS – HARD-EARNED EXPERIENCES

Blog #19: Chrome Performance Tab – Looking through a microscope at the system's pulse

Don't guess, measure. A guide to understanding Frame, Task, and Thread charts to find the silent 'killers' in your application.

TP
Truong PhamSoftware Engineer
PublishedMay 2, 2024

"This app occasionally hitches for about half a second when I hit the Submit button. I don't see any errors in the Console, the network reports OK, so what's wrong with it?"

This is when simple tools like console.log or the Network Tab become useless. To solve this problem, you must resort to the "ultimate weapon" of a Frontend Engineer: the Chrome Performance Tab. Instead of looking at individual lines of code, we will look through a microscope at the entire System Heartbeat.

1. Overall Architecture: Understanding the "Flame Chart"

When you hit Record in the Performance Tab, the browser records everything from CPU, GPU, and Network activity. The result is a maze of colored blocks. From a system perspective, notice three survival "colors":

  • Yellow (Scripting): The CPU is "sweating" to run JavaScript.
  • Purple (Rendering): The browser is calculating where elements are (Style & Layout).
  • Green (Painting): The browser is drawing pixels onto the screen.

The "hitch" users complain about usually appears as Long Tasks—yellow blocks longer than 50ms. When a long task appears, it occupies the Main Thread, preventing the browser from responding to any other interaction. The system is temporarily "paralyzed."

2. Analysis of Task Flow

Look at how the system queues work:

  • Task Flow: Click Event → Task Queue → Main Thread → Execution (Long Task!) → Queue blocked! → UI Freeze.
  • Symptoms: Small red bars above the yellow blocks are signs of "System Pain" (the system is hurting).
/* Error: A "giant" task blocking the system */
function handleSubmit() {
  processLargeData(); // Takes 300ms, Main Thread stays frozen
  sendAPI();
}

/* System Thinking: Divide and Conquer */
function handleSubmit() {
  // Break down tasks or use a Web Worker
  scheduler.postTask(() => processLargeData()); 
  // Or use setTimeout(..., 0) to give the UI room to breathe
}

3. Quick Fix vs. Architectural Refactoring

Quick Fix: Add a Spinner that covers the entire screen. This is a way to "trick" the senses. The user still has to wait, and the application is still frozen behind that Spinner.

Architectural Refactoring (Architectural Fix):

  1. Task Splitting: Use the scheduler.yield() API or techniques to slice up loops so the Main Thread always has Idle periods to handle user interaction.
  2. Batching: Group state changes together to avoid the browser having to calculate Layout/Paint unnecessarily.
  3. Offloading: Move heavy data processing logic into Web Workers. Then, the Main Thread has only one mission: Keep the UI smooth.

4. Technical Debt and Self-Reflection

Not knowing how to read the Performance Tab is a major shortcoming for a Senior Engineer. We often tend to "guess" errors based on experience, leading to fixing the wrong place and increasing code complexity without solving the root system problem.

I wonder: "Am I trying to cram too much logic onto the client side?". Sometimes, the best solution for an overloaded Frontend system is to push data processing back to the Backend. Don't try to turn the browser into a supercomputer—keep it as a lean display interface.

Lesson Learned

System performance is the result of Yielding. A good component is not the one that runs the fastest, but the one that knows when to stop to give priority to the user. Don't let your application "stop breathing" just because of one greedy piece of code.


Notes on the precious silences of the main thread.

Series • Part 19 of 50

50 FRONTEND LESSONS – HARD-EARNED EXPERIENCES

NextBlog #20: The Mystery of LCP – Why do 'fast' websites still get rated low?
Blog #18: Laggy Animations – When the touch is no longer smooth
14Blog #14: The Domino Effect – When one small change crashes the whole Render system15Blog #15: The 10,000-Row Lesson – When Table Virtualization saved my career16Blog #16: Misplaced Debounce – When a localized solution becomes a system burden17Blog #17: Images vs JS – The battle for priority in the Critical Path18Blog #18: Laggy Animations – When the touch is no longer smooth19Blog #19: Chrome Performance Tab – Looking through a microscope at the system's pulseReading20Blog #20: The Mystery of LCP – Why do 'fast' websites still get rated low?21Blog #21: The Global State Nightmare – The decision to 'topple' the Redux monument22Blog #22: Click Race Condition – When User's click speed beats your App23Blog #23: Multi-tab Syncing – When your application 'talks' between tabs24Blog #24: Failed Optimistic Update – When efforts to 'smooth' UI turn into UX disasters
TP

Written by Truong Pham

Software Engineer passionate about building high-performance systems and meaningful experiences.

Read more articles