Transaction vs. Continuous & UI Profiling

Learn about the differences between transaction-based Profiling and the new Continuous & UI Profiling products.

We’ve released two new products: Continuous Profiling (focused on backend applications) and UI Profiling (focused on frontend applications) with the intent of replacing our prior transaction-based profiling product. Read on to learn more about the differences between these implementations.

Our initial implementation of profiling is what we refer to throughout this document as transaction-based profiling. As the name suggests, in this mode, profiling was coupled to the lifecycle of a transaction (a term we use to describe a root span). When the transaction started, profiling was automatically started, and when the transaction finished, profiling was automatically finished. This meant that if you application was already instrumented with tracing, profiling could be enabled with minimal additional effort. While this approach simplified set up, it came with some drawbacks.

One major limitation was that profiles couldn’t exceed 30 seconds in duration. Since profiles had to be sent alongside their corresponding transaction, the SDKs would need to buffer the profiling data on the client for the entire duration of the transaction. Transactions can be arbitrarily long, but profile payloads are large compared to spans, and therefore we could not buffer profiling data indefinitely without risking excess memory usage and OOM (out-of-memory) states on the client. Because of this limitation, it was not possible to use transaction-based profiling for longer running operations (e.g. profiling complete user sessions on the frontend, or long running tasks on the backend)

Another limitation was that by coupling to transactions, profiling was limited to only the places in the application that had adequate tracing instrumentation coverage. If some part of the application was not instrumented with spans, there would also be no profiling data collected. The existence of these data gaps makes it difficult to accurately determine what the most serious performance bottlenecks are.

Continuous Profiling & UI Profiling were designed to address these limitations and provide more powerful profiling capabilities that are useful in a wider range of scenarios. These products have no cap on the maximum profile length because profile data is streamed in chunks, and they provide complete control over when the profiler is running.

The Continuous Profiling product was designed to help debug performance bottlenecks on backend applications and services. The recommended way of using Continuous Profiling is to start the profiler when a service starts, and stop profiling when the service is terminated. By running the profiler continuously throughout the service’s lifetime, Sentry can provide complete visibility into codepaths that might be causing excessive resource usage resulting in high infrastructure costs.

Continuous Profiling usage can be constrained in multiple ways in case you are concerned about cost or performance overhead:

  • Using client-side sampling controls to collect profiles on fewer instances of the same service (e.g. only profile 10% of the instances of a service)
  • Use the start_profiler and stop_profiler APIs to selectively profile only known performance-critical parts of the service

The UI Profiling product was designed to help debug performance bottlenecks on frontend applications. These bottlenecks typically cause user-facing issues like janky scrolling or animations, high interaction latency, and slow loading times. The recommended way of using UI Profiling is to start the profiler when the user session begins, and stop profiling when the user session ends (when the application is terminated, or, if on mobile, when the application is backgrounded). By profiling complete user sessions, Sentry can provide complete visibility into codepaths that might be degrading the user experience and causing excessive battery usage on the user’s device.

UI Profiling usage can be constrained in multiple ways in case you are concerned about cost or performance overhead:

  • Using client-side sampling controls to collect profiles on fewer user sessions (e.g. only profile 10% of all user sessions)
  • Use the start_profiler and stop_profiler APIs to selectively profile only known performance-critical parts of the application

Continuous Profiling & UI Profiling expose two new lifecycle modes that help you control exactly how profiling behaves in your application.

The manual lifecycle mode provides complete control over when the profiler is running through the use of new start_profiler and stop_profiler APIs. This is the default lifecycle mode. If start_profiler is not called, profiling data will never be collected.

One of the benefits of transaction-based profiling was the simplicity of being able to collect profiles alongside traces automatically without having to manually instrument the codebase. The trace lifecycle mode provides a behavior that is similar to the old transaction-based profiling behavior, where profiling will be automatically started and stopped when there is an active transaction or root span. This lifecycle mode does not require manual calls to start_profiler, but does require that tracing is enabled and that the application has been instrumented with spans.

As with transaction-based profiling, Continuous Profiling & UI Profiling support client-side sampling controls. However, sampling now occurs at a session scope rather than at an individual profile scope. For more information on how sampling works, read the migration guide.

If you are an existing user of transaction-based profiling, read the migration guide for instructions on how to migrate to the new APIs.

If you are a new user, read the getting started guide for the SDK that you’re using.

Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").