Skip to main content

Main thread performance

Issue summary

Component resolution is running on the main thread for too long, exceeding the defined threshold. This leads to ANRs (Application Not Responding), where the app becomes unresponsive and appears frozen. Common causes include heavy computations or synchronous operations running on the main thread.

Platform target and tolerance:

  • Target: 100 ms
  • Tolerance: up to 400 ms

Why it matters

When the main thread is blocked, the app can’t respond to user interactions causing it to freeze and so frustrating users. This degrades the user experience, increases app abandonment, and hurts app store ratings.

How severity is calculated

The platform calculates a severity score for main thread blocking issues based on how much the measured blocking time exceeds the defined target and tolerance.

SeverityDefinition
No issue raisedMain thread blocking ≤ 100 ms. No significant issue.
Low–MediumBlocking exceeds target but is within tolerance (100–400 ms). Gradual impact based on distance from midpoint.
High–CriticalBlocking exceeds tolerance (> 400 ms). Score capped at 100, indicating maximum severity.

How to fix a main thread performance issue

Since the Kotzilla platform has detected a main thread blocking problem, your focus should now be on investigating what’s happening during component initialization especially which operations are running too long on the UI thread.

Focus on:

  • Avoiding long-running tasks anytime the main/UI thread is active
  • Ensuring that even when resolving or creating components dynamically during the app’s lifecycle, no operation blocks the main thread
  • Offloading heavy work to background threads and ensuring async resolution patterns
  1. Offload heavy work to background threads
    Main thread blocking usually happens when time-consuming tasks like database queries, network requests, or heavy computations run directly on the UI thread. To prevent this, ensure these operations are executed on background threads using the right coroutine dispatchers (Dispatchers.Default). This allows the main thread to stay free for user interactions and keeps the app responsive.

  2. Apply lazy dependency loading
    Even though Koin singletons are lazy by default, it’s important to avoid accidentally forcing early initialization using createdAtStart() or premature get() calls. Instead, use the inject() approach inside your classes to request dependencies only when they are actually accessed. This is especially useful for non-critical services, like analytics or remote configuration, which don’t need to be initialized right away.

  3. Refactor and isolate heavy components
    A complex or tightly coupled dependency graph can still lead to indirect main thread blocking, even with lazy loading. To improve this, break down large or multi-responsibility components into smaller, focused modules. Reduce unnecessary coupling between dependencies and isolate heavy or optional components so they can be resolved separately or loaded asynchronously. This reduces the resolution load on the main thread and improves overall performance.

Use the Kotzilla SDK API and the Console to help you with the investigation

You can use the Kotzilla SDK API to instrument and trace component initialization code that might be causing main thread blocking. Add custom logs, measure execution time, and capture contextual data around the initialization of your components.

This information will appear on the Timeline View of the Kotzilla Console for each impacted user session. You can also get a visual representation of the different thread executions for each user session, helping you better understand how specific component resolutions are impacting thread behaviour.

For full setup and usage details, check the Kotzilla SDK API documentation.

Need help?

Slow components resolutions are driving you crazy? Our experts are just a click away, reach out anytime for best practices and pro tips!