Skip to content

perf: Replace java.net.URI with custom string parsing in Dsn#5448

Merged
runningcode merged 6 commits into
mainfrom
no/custom-dsn-parser
Jun 9, 2026
Merged

perf: Replace java.net.URI with custom string parsing in Dsn#5448
runningcode merged 6 commits into
mainfrom
no/custom-dsn-parser

Conversation

@runningcode

@runningcode runningcode commented May 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Replaces java.net.URI parsing in the Dsn constructor with lightweight manual
string parsing, and hardens and tests the parser. This is a critical startup path performance improvement.

Here are perfetto traces of the retrieveParsedDsn() method as measured on a Pixel 3. I've repeated the measurement several times and I always get an order of magnitude difference.

This is on master:
image
This is on this branch:
image

What changed

  • Parsing: Replace new URI(dsnString).normalize() with manual
    indexOf/substring parsing, avoiding the java.net.URI string parser.
    retrieveParsedDsn() runs on the main thread during Sentry.init(), so this
    keeps a known-slow API off the init path. The only remaining URI use is
    constructing the endpoint from already-parsed components
    (new URI(scheme, null, host, port, path, null, null)), which does not
    re-parse a string.
  • Correctness: Strip URI fragments (#…) alongside query strings so they no
    longer leak into the project id, and support bracketed IPv6 literal hosts
    (e.g. https://key@[::1]:9000/1) — both behaviors the old URI parser handled.

JAVA-532

Relates to: https://linear.app/getsentry/issue/JAVA-532
Also relates to: https://linear.app/getsentry/issue/JAVA-516/move-dsn-parsing-off-the-main-thread-during-init

🤖 Generated with Claude Code

@linear-code

linear-code Bot commented May 19, 2026

Copy link
Copy Markdown

JAVA-516

JAVA-532

@sentry

sentry Bot commented May 19, 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

@github-actions

github-actions Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 322.24 ms 395.65 ms 73.41 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
91bb874 314.47 ms 440.00 ms 125.53 ms
2195398 309.39 ms 354.53 ms 45.14 ms
9770665 315.64 ms 378.00 ms 62.36 ms
abfcc92 337.38 ms 427.39 ms 90.00 ms
b77456b 393.26 ms 441.10 ms 47.84 ms
8687935 332.52 ms 362.23 ms 29.71 ms
14ff5ee 419.75 ms 495.73 ms 75.98 ms
48277cd 320.38 ms 379.90 ms 59.52 ms
694d587 305.45 ms 378.38 ms 72.94 ms
4c04bb8 350.71 ms 413.63 ms 62.92 ms

App size

Revision Plain With Sentry Diff
91bb874 1.58 MiB 2.13 MiB 559.07 KiB
2195398 0 B 0 B 0 B
9770665 0 B 0 B 0 B
abfcc92 1.58 MiB 2.13 MiB 557.31 KiB
b77456b 1.58 MiB 2.12 MiB 548.11 KiB
8687935 1.58 MiB 2.19 MiB 619.17 KiB
14ff5ee 1.58 MiB 2.10 MiB 535.08 KiB
48277cd 0 B 0 B 0 B
694d587 1.58 MiB 2.19 MiB 620.06 KiB
4c04bb8 0 B 0 B 0 B

Previous results on branch: no/custom-dsn-parser

Startup times

Revision Plain With Sentry Diff
96d1d4a 354.34 ms 443.40 ms 89.06 ms
2f05649 287.89 ms 353.78 ms 65.89 ms
85d9e31 323.66 ms 391.76 ms 68.10 ms
51a27f4 318.65 ms 361.66 ms 43.01 ms

App size

Revision Plain With Sentry Diff
96d1d4a 0 B 0 B 0 B
2f05649 0 B 0 B 0 B
85d9e31 0 B 0 B 0 B
51a27f4 0 B 0 B 0 B

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit cacc249. Configure here.

Comment thread sentry/src/main/java/io/sentry/Dsn.java Outdated
Comment thread sentry/src/main/java/io/sentry/Dsn.java Outdated

@0xadam-brown 0xadam-brown left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A few optionals; otherwise lgtm

Comment thread sentry/src/main/java/io/sentry/Dsn.java Outdated
Comment thread sentry/src/main/java/io/sentry/Dsn.java Outdated
Comment thread sentry/src/main/java/io/sentry/Dsn.java Outdated
Comment thread sentry/src/test/java/io/sentry/DsnTest.kt Outdated
@runningcode runningcode changed the title perf: Replace java.net.URI with custom string parsing in Dsn [DNM] [Don't review] perf: Replace java.net.URI with custom string parsing in Dsn May 28, 2026
@runningcode runningcode force-pushed the no/custom-dsn-parser branch from cacc249 to 4851e6d Compare June 4, 2026 14:07
Comment thread sentry/src/main/java/io/sentry/Dsn.java
@runningcode runningcode changed the title [DNM] [Don't review] perf: Replace java.net.URI with custom string parsing in Dsn perf: Replace java.net.URI with custom string parsing in Dsn Jun 4, 2026

@0xadam-brown 0xadam-brown left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the updates – lgtm 👍

Comment thread gradle/libs.versions.toml
Comment thread sentry/src/main/java/io/sentry/Dsn.java Outdated
Comment thread sentry/src/main/java/io/sentry/Dsn.java

@romtsn romtsn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

one nit, but LGTM otherwise! great gains

runningcode and others added 6 commits June 9, 2026 09:39
The Dsn constructor used `new URI(dsnString).normalize()` to parse the
DSN string, which is known to be slow on Android. Since `retrieveParsedDsn()`
is called on the main thread during `Sentry.init()` via
`preInitConfigurations()`, this directly impacts app startup time.

Replace the URI-based parsing with manual indexOf/substring operations.
The only remaining URI construction is from pre-parsed components
(`new URI(scheme, null, host, port, path, null, null)`), which is
significantly cheaper since the JDK doesn't need to re-parse a string.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cover edge cases specific to the manual indexOf/substring parser:
null input, missing scheme separator, no slash after host, multiple
path segments, port with path, multiple double slashes, query string
with port, empty secret key, and a realistic Sentry DSN with org id.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Harden the custom DSN parser and convert its tests to Google Truth.

- Strip URI fragments (#...) alongside query strings so they no longer
  leak into the project id and corrupt the constructed Sentry URI.
- Detect bracketed IPv6 literal hosts when locating the port separator,
  restoring behavior that java.net.URI handled.
- Narrow the parse error handling from catch (Throwable) to the
  expected exceptions, which stops swallowing Error and removes the
  doubled exception message.
- Extract the parsing steps into focused private helpers.
- Convert DsnTest to Google Truth assertions.
- Move the changelog entry to the Unreleased section, since 8.43.0 and
  8.43.1 have already been released.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Follow Truth's recommended pattern for exception testing: catch with
assertFailsWith, then assert on the caught throwable with
assertThat(ex).hasMessageThat(). Also assert the message in the
previously bare throw-only cases so they can no longer pass on an
unrelated exception.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Parse the port in a dedicated helper that reports the offending value
("Invalid DSN: Invalid port 'abc'.") instead of leaking the raw
NumberFormatException text. Narrow the catch to URISyntaxException now
that the port is the only parseInt, and add a test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@runningcode runningcode force-pushed the no/custom-dsn-parser branch from 88dc031 to 7d400c0 Compare June 9, 2026 07:40
@runningcode runningcode merged commit 29f120b into main Jun 9, 2026
68 checks passed
@runningcode runningcode deleted the no/custom-dsn-parser branch June 9, 2026 08:22
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.

3 participants