Skip to content

Avoid Thread.getName() string scan on the scope-persistence hot path #5687

Description

@runningcode

Problem

PersistingScopeObserver.serializeToDisk decides whether it is already on the Sentry executor thread by scanning the thread name:

if (Thread.currentThread().getName().contains("SentryExecutor")) {
  task.run();
  return;
}

Thread.getName() allocates a fresh String and .contains() scans it — on every scope mutation (breadcrumb, tag, trace, user, etc.). In the trace this path runs 3,000+ times, including on the main thread as the synchronous part of addBreadcrumb.

Evidence

From on-device method trace analysis (median.perfetto-trace): PersistingScopeObserver#addBreadcrumb sync part was ~10ms main-thread self-time / 65 calls, and the same serializeToDisk gate runs for all ~3,130 scope stores. The string allocation + scan is pure overhead on a very hot path.

Fix

The executor already uses a dedicated SentryExecutorServiceThreadFactory (SentryExecutorService). Tag those threads (a marker Thread subclass or a ThreadLocal<Boolean> set in newThread) and replace the name scan with an allocation-free identity/boolean check:

if (SentryExecutorThreadMarker.isCurrentThreadSentryExecutor()) {
  task.run();
  return;
}

Keep the marker package-private/internal so there is no public API change.

Acceptance

No String allocation on the serializeToDisk thread check; the on-executor fast-path still short-circuits correctly; no .api change.

Metadata

Metadata

Assignees

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions