All jobs / Mobile developer

Performance interview questions

Performance questions a Mobile developer can be asked, from first job to senior. Open one to see the strongest answer and why it works.

  1. The UI freezes for a beat every time a row appears. What is the most likely cause?

    The strongest answer: Work on the main thread during bind or layout — JSON parse, disk, a large image decode, or a sync query

    Why it works: Exactly. Frames drop when the UI thread is busy. Move the work off, then re-bind.

    • Jank is usually main-thread work.
    • Profile bind, layout, and decode.
    • Move I/O and decode off the UI thread.
    • Re-bind when the result is ready.
  2. A list of a few thousand rows stutters when you scroll. What do you check first?

    The strongest answer: That rows are recycled / reused, that I am not inflating a new heavy view per bind, and that images are sized for the cell not the original file

    Why it works: Exactly. Recycling, cheap bind, and correctly sized images fix most first-year jank.

    • Reuse cells; do not rebuild the tree per row.
    • Bind must be cheap — no decode, no layout thrash.
    • Decode images to the cell size.
    • Measure before you rewrite the architecture.
  3. The app polls the server every thirty seconds so new messages show up quickly. Why is that a problem on a phone, and what do you use instead?

    The strongest answer: Every poll wakes the radio and the device, so it costs battery and data even when nothing has changed. Let the server push when there is something new, and refresh when the user opens the screen

    Why it works: Exactly — the cost is waking the radio, not the size of the request, which is why frequency is what hurts.

    • Waking the radio is the cost.
    • Push beats polling for freshness.
    • Refresh on open, not on a timer.
    • Batch whatever must be periodic.
  4. Images in a grid still spike memory after you added a cache. What did you miss?

    The strongest answer: I am decoding / caching the original bytes at full resolution — I should decode to the view size and let the cache evict under memory pressure

    Why it works: Exactly. Cache the right size. A 12 MP decode into a 100 pt cell is the spike.

    • Decode to the displayed size.
    • Let the cache evict.
    • Watch memory, not only disk hits.
    • Do not pin gigabytes of bitmaps.
  5. A WebView screen is used for checkout, then the user goes back. What do you clean up?

    The strongest answer: Cookies / sessions you do not want to persist, JS bridges, and the WebView instance itself — a retained WebView is a leak and sometimes a logged-in ghost

    Why it works: Exactly. WebView state is real session state. Destroy and decide cookies on purpose.

    • Destroy the WebView when the screen is gone.
    • Decide cookie persistence explicitly.
    • Tear down JS bridges.
    • Do not share one engine across users.
  6. Cold start has drifted to several seconds. Five SDKs initialise before the first screen appears.

    How do you get it back?

    The strongest answer: Measure what runs before the first frame, move anything that frame does not need off the startup path — lazily on first use, or after the screen is drawn — and add a startup check to CI

    Why it works: Right — measure, defer, then guard. Without the guard the same five seconds come back one dependency at a time.

    • Measure before the first frame.
    • Only first-frame work at startup.
    • Initialise lazily or after paint.
    • Guard startup time in CI.
  7. A “perfectly virtualized” list still drops frames on mid phones. What do you inspect next?

    The strongest answer: The size of the overscan window, span counts, placeholder vs real bind cost, and whether I am measuring every row on the UI thread — virtualization is necessary, not sufficient

    Why it works: Exactly. Window, span, and measure cost are the next knobs. Profile them.

    • Profile overscan and measure.
    • Keep placeholders cheaper than the real row.
    • Watch span / grid costs.
    • Do not “fix” frames by changing the store device floor first.
  8. Memory climbs every time the user opens and closes the same screen, and it never comes back down.

    How do you find it?

    The strongest answer: Take a heap snapshot after several open-and-close cycles and look for screens that should be gone. The usual holder is something long-lived — a listener, a singleton, a callback, or a strong reference captured in a closure

    Why it works: Exactly — prove which object is retained and by whom before changing code; guessing at leaks costs days.

    • Prove the retention, then fix it.
    • Snapshot after repeated open-and-close.
    • Find who still holds the screen.
    • Break the strong reference back.
  9. How do you keep a mobile (or RN) surface from getting slower every quarter?

    The strongest answer: Budgets on startup, scroll, and binary size, measured on a reference device in CI, with a break-the-build or a written exception — not a yearly “perf week”

    Why it works: Exactly. Budgets on the train. Perf week is a confession.

    • Name the budgets.
    • Measure on a reference device.
    • Break the build or write the exception.
    • Same discipline as a web performance budget.
  10. The app is in “battery hog” stories. How do you run that as a platform?

    The strongest answer: Budgets for background wakeups, radio, and unmetered vs metered, with traces and a squad-level owner — I do not answer with a single “we use WorkManager” slogan

    Why it works: Exactly. Battery is a budget with owners and traces. Slogans do not drain less.

    • Budget wakeups and bytes.
    • Trace the radio.
    • Do not ask users to exempt you.
    • Own it as a platform, not a ticket.