Skip to content

perf: Drop pending timer tasks on shutdown to unblock close (JAVA-653) - #5851

Open
runningcode wants to merge 2 commits into
mainfrom
no/perf/timer-executor-shutdown-policy
Open

perf: Drop pending timer tasks on shutdown to unblock close (JAVA-653)#5851
runningcode wants to merge 2 commits into
mainfrom
no/perf/timer-executor-shutdown-policy

Conversation

@runningcode

@runningcode runningcode commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

This is a follow up on this comment: https://github.com/getsentry/sentry-java/pull/5814/changes#r3667006204

The timer executor is shut down in Scopes.close() via shutdown() followed by awaitTermination(shutdownTimeoutMillis). ScheduledThreadPoolExecutor keeps queued delayed tasks across shutdown() by default, so awaitTermination blocks for the full shutdown timeout (2s by default) whenever a long timeout is still pending at close time:

  • an unfinished transaction's idle/deadline timer (SentryTracer)
  • the 30s LifecycleWatcher end-session task, only cancelled on foregrounding
  • a rate limit lifted notification (RateLimiter, up to retry_after)

Setting executeExistingDelayedTasksAfterShutdownPolicy(false) drops those tasks at shutdown() instead. This is behaviour preserving: today they are discarded by the subsequent shutdownNow() once the timeout expires anyway, so the only thing lost is the wait.

The policy only affects shutdown(), so the SDK restart path that intentionally leaves the timer executor running (Scopes.close(isRestarting = true)) is unaffected. Scoped to the timer executor's constructor — the general-purpose executor keeps the default.

Measured with a standalone repro using the same executor configuration, one pending 60s task and a 2s timeout:

terminated blocked
before false 2000ms
after true 0ms

🤖 Generated with Claude Code

The timer executor is shut down by Scopes.close() via shutdown() followed
by awaitTermination(). ScheduledThreadPoolExecutor keeps queued delayed
tasks across shutdown() by default, so awaitTermination() blocks for the
full shutdown timeout (2s by default) whenever a long timeout is still
pending: an unfinished transaction's idle/deadline timer, the 30s
LifecycleWatcher end-session task, or a rate limit lifted notification.

Those tasks are discarded by the subsequent shutdownNow() anyway, so
dropping them upfront is behaviour preserving and only saves the wait.
This only affects shutdown(), so the SDK restart path that intentionally
leaves the timer executor running is unaffected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jul 29, 2026

Copy link
Copy Markdown

JAVA-653

@sentry

sentry Bot commented Jul 29, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.50.0 (1) release

⚙️ sentry-android Build Distribution Settings

@github-actions

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 411.49 ms 476.82 ms 65.33 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
6b019b7 319.84 ms 333.15 ms 13.31 ms
c3ee041 310.64 ms 361.90 ms 51.26 ms
d501a7e 348.06 ms 431.42 ms 83.36 ms
3998a95 415.94 ms 478.54 ms 62.60 ms
ed33deb 343.30 ms 362.41 ms 19.10 ms
5b1a06b 310.56 ms 362.79 ms 52.22 ms
91bb874 310.68 ms 359.24 ms 48.56 ms
0ee65e9 317.37 ms 366.50 ms 49.13 ms
6edfca2 305.52 ms 432.78 ms 127.26 ms
5e269de 292.83 ms 379.12 ms 86.29 ms

App size

Revision Plain With Sentry Diff
6b019b7 0 B 0 B 0 B
c3ee041 0 B 0 B 0 B
d501a7e 0 B 0 B 0 B
3998a95 1.58 MiB 2.10 MiB 532.96 KiB
ed33deb 1.58 MiB 2.13 MiB 559.52 KiB
5b1a06b 0 B 0 B 0 B
91bb874 1.58 MiB 2.13 MiB 559.07 KiB
0ee65e9 0 B 0 B 0 B
6edfca2 1.58 MiB 2.13 MiB 559.07 KiB
5e269de 0 B 0 B 0 B

}

@Test
fun `SentryExecutorService discards pending delayed tasks on shutdown when requested`() {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure we really need these tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant