Typing into an Angular product filter panel feels laggy; how would you use Angular's profiling tools to find which component's change detection is responsible?
answer
- reproduce in a development build
- count and height of bars per keystroke
- dominant component, then its method
- which subtrees were checked
- Angular track versus the rest
basics
~20 sRecord the typing in the Angular DevTools Profiler, check how many cycles each keystroke causes and how tall they are, open the tallest to find the dominant component and method, then confirm with the Chrome Angular track whether the time is Angular's.
solid answer
~40 sReproduce the lag in a development build and record a few keystrokes in the **Profiler**. First read the shape: one short cycle per keystroke is healthy; several cycles per keystroke, or tall ones, is the lead. Select the tallest bar, read the component bar chart, and open the dominant entry to see whether its template function or a hook such as `ngDoCheck` consumed the time. Switch to the flame graph with **Change detection** ticked to see whether subtrees unrelated to the filter, like a results grid, are being checked at all. If the cycles are short but typing still lags, record a Chrome Performance trace with `enableProfiling()`: a long task without Angular entries points at layout, paint or another script. Fix, re-record the same keystrokes, and compare saved profiles.
go deeper
Recall that you record the interaction in the Angular DevTools Profiler and look for tall change detection bars.
Explain how to drill from the tallest cycle to the dominant component and whether its template or a hook took the time.
Run the full diagnosis: cycle count and height, dominant component, unexpected checked subtrees, the Chrome Angular track, then a before-and-after comparison.
Turn this into a repeatable team practice: saved profiles attached to performance bugs, with production-like confirmation before closing them.
## The scenario A product catalogue has a **filter panel**: a text box, some checkboxes and a price slider, next to a results grid. Users report that typing into the text box lags; characters appear in bursts. The task is to find **which component's change detection** is responsible before changing any code. ## Step 1: reproduce under the right conditions - Use a **development build** (`ng serve` by default), because Angular DevTools and `enableProfiling()` only work there. - Use realistic data: the grid with its usual number of products, not an empty mock. - Keep the interaction repeatable, for example typing the same five characters each time. Development builds do extra checking work, so expect absolute times to be higher than in production. What you are looking for is **relative** cost. ## Step 2: read the shape of the recording Start the **Profiler**, type the five characters, stop. Before opening any bar, read the timeline: | Pattern | What it suggests | |---|---| | One short bar per keystroke | Change detection is not the problem; look at the Chrome trace | | One tall bar per keystroke | One cycle is expensive; find the dominant component | | Several bars per keystroke | Something triggers extra cycles, such as timers or chained updates | | Bars growing over time | Work accumulates, for example a list that keeps growing | ## Step 3: find the dominant component Select the tallest bar: 1. Read the cycle's **total time** and the **estimated frame rate** if it dropped below 60 fps. 2. In the **bar chart**, identify the component or directive that dominates. In this scenario it is often the results grid, not the filter panel itself. 3. Click it to see **which methods** consumed the time: the template function (expensive bindings, methods called per row) or a hook such as `ngDoCheck`. 4. Note its **parent hierarchy**, which tells you whether it sits under the filter panel or elsewhere. If no single component dominates, switch to the **flame graph**: a wide subtree of many cheap rows reveals cost that the bar chart spreads thin. ## Step 4: check what should not have been checked Tick the **Change detection** checkbox above the flame graph. Components that were not checked turn grey. Typing in the filter text box should check the panel and its ancestors; if the whole results grid is coloured on every keystroke, ask why: - the grid receives a **new array reference** on every check (a filter done in a template method); - the grid or a parent uses the **`Eager`** strategy; - the grid reads a **signal** that each keystroke writes, which may be correct if the grid really filters live. That last case is legitimate work, and the question becomes how much of it is needed per keystroke. ## Step 5: place Angular's work in the whole frame If Angular's cycles are short but typing still lags, record a Chrome **Performance** trace with `enableProfiling()` called at startup (or `ng.enableProfiling()` from the console): - a long task with **no Angular track entries** belongs to layout, paint or another script; - a change detection entry with **several synchronization passes** means state is written during the check; - nesting on the Angular track shows **which template update or hook** sits inside the long task. ## Step 6: fix and verify The fix belongs to whichever cause you found, for example memoizing a per-row calculation or giving the grid a stable input. The profiling part is verification: **save the before profile as JSON**, apply the fix, record the same keystrokes, and compare. The fix is real when the tall bars shrink or the grid turns grey in the change detection view, and it is confirmed when a production-like build also feels responsive. ## What interviewers listen for - Measuring before guessing, with a repeatable interaction. - Reading **count** and **height** of cycles, not only the tallest bar. - Separating "which component is slow" from "which components should not have been checked". - Knowing that the tools are development-only and that their numbers are relative. - Leaving the fix itself to the evidence: the profiler names a component and a method, and only then does memoization, a stable input or a narrower signal become the obvious change.
- The Profiler shows one short cycle per keystroke, but typing still lags. What next?Change detection is not the bottleneck. Record a Chrome Performance trace with `enableProfiling()` on: if the long task has no Angular entries, the time is layout, paint or another script, and the fix lies there. If Angular entries show several synchronization passes, look for state written during the check.
- Why compare saved profiles instead of just re-testing by feel?Feel is noisy and development builds are slower than production anyway. Two saved recordings of the same keystrokes show whether the tall cycles shrank and whether the grid stopped being checked, which is evidence you can attach to the change.
saying these in an interview costs you the question
- The tallest bar alone tells you everything; bar count does not matter
- Profiler times are production latencies users will see
- If the filter panel is slow, the filter panel component must be the cause
- A checked results grid is always a bug, even when it filters live
- Short change detection cycles prove the page has no main-thread problem