Skip to content

perf(core): Use fixed-delay scheduling for performance collector (JAVA-555)#5524

Open
runningcode wants to merge 4 commits into
mainfrom
no/perf-collector-fixed-delay-scheduling
Open

perf(core): Use fixed-delay scheduling for performance collector (JAVA-555)#5524
runningcode wants to merge 4 commits into
mainfrom
no/perf-collector-fixed-delay-scheduling

Conversation

@runningcode

@runningcode runningcode commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

📜 Description

Switch the transaction collection timer in DefaultCompositePerformanceCollector from Timer.scheduleAtFixedRate to Timer.schedule (fixed-delay scheduling).

Fixes JAVA-555.

💡 Motivation and Context

scheduleAtFixedRate schedules tasks relative to the initial start time, so after a delay or GC pause it fires a burst of rapid catch-up executions to "make up" for missed runs. The old code defended against this with a 10ms skip check, since collections spaced closer than that are not meaningful. In addition, it is using System.currentTimeMillis() which isn't a monotonic clock meaning it could go forwards and then guard is broken allowing all the tasks to run.

schedule uses fixed-delay scheduling: each collection is scheduled 100ms after the previous one finishes. Catch-up bursts can no longer happen, so the guard and its supporting state are redundant. The result is more even collection spacing and simpler code.

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

runningcode and others added 2 commits June 10, 2026 17:23
Switch the transaction collection timer from scheduleAtFixedRate to
schedule. Fixed-rate scheduling fires rapid catch-up executions after a
delay or GC pause, which the old code guarded against with a 10ms skip
check. Fixed-delay scheduling spaces each collection 100ms after the
previous one finishes, so the catch-up bursts cannot happen and the
guard, its timestamp field, and the stale comment are no longer needed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
new TimerTask() {
@Override
public void run() {
long now = System.currentTimeMillis();

@runningcode runningcode Jun 10, 2026

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.

The issue is that scheduleAtFixedRate could schedule thousands of tasks in a row if the system goes in to deep sleep but then we guard against it using this System.currentTimeMillis() which isn't a monotonic clock meaning it could go forwards and then guard is broken allowing thousands of tasks to run.

The performance collector now uses fixed-delay scheduling, so the timer
verifications assert schedule(...) rather than scheduleAtFixedRate(...).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@runningcode runningcode marked this pull request as ready for review June 10, 2026 15:40
@runningcode runningcode changed the title perf(core): Use fixed-delay scheduling for performance collector perf(core): Use fixed-delay scheduling for performance collector (JAVA-555) Jun 10, 2026
@linear-code

linear-code Bot commented Jun 10, 2026

Copy link
Copy Markdown

JAVA-555

@sentry

sentry Bot commented Jun 10, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

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

⚙️ sentry-android Build Distribution Settings

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