perf: Replace java.net.URI with custom string parsing in Dsn#5448
perf: Replace java.net.URI with custom string parsing in Dsn#5448runningcode wants to merge 3 commits into
Conversation
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>
📲 Install BuildsAndroid
|
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 27d7cf8 | 309.43 ms | 364.27 ms | 54.85 ms |
| ee35ac3 | 346.83 ms | 435.48 ms | 88.65 ms |
| 2124a46 | 319.19 ms | 415.04 ms | 95.85 ms |
| f6cdbf0 | 314.19 ms | 357.59 ms | 43.40 ms |
| 22f4345 | 325.23 ms | 454.66 ms | 129.43 ms |
| fcec2f2 | 357.47 ms | 447.32 ms | 89.85 ms |
| f064536 | 329.00 ms | 395.62 ms | 66.62 ms |
| bb0ff41 | 344.70 ms | 413.82 ms | 69.12 ms |
| d15471f | 361.89 ms | 378.07 ms | 16.18 ms |
| e59e22a | 368.02 ms | 432.00 ms | 63.98 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 27d7cf8 | 1.58 MiB | 2.12 MiB | 549.42 KiB |
| ee35ac3 | 1.58 MiB | 2.13 MiB | 558.77 KiB |
| 2124a46 | 1.58 MiB | 2.12 MiB | 551.51 KiB |
| f6cdbf0 | 0 B | 0 B | 0 B |
| 22f4345 | 1.58 MiB | 2.29 MiB | 719.83 KiB |
| fcec2f2 | 1.58 MiB | 2.12 MiB | 551.50 KiB |
| f064536 | 1.58 MiB | 2.20 MiB | 633.90 KiB |
| bb0ff41 | 0 B | 0 B | 0 B |
| d15471f | 1.58 MiB | 2.13 MiB | 559.54 KiB |
| e59e22a | 1.58 MiB | 2.20 MiB | 635.34 KiB |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ 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.
| final String hostAndPath = | ||
| queryIndex < 0 | ||
| ? dsnString.substring(hostStart) | ||
| : dsnString.substring(hostStart, queryIndex); |
There was a problem hiding this comment.
URI fragment not stripped, corrupts projectId silently
Low Severity
The new parser strips query strings (?...) but never strips URI fragments (#...). The old java.net.URI.getPath() automatically excluded fragments. If a DSN contains a # (e.g. https://key@host/123#frag), the fragment leaks into projectId (becoming 123#frag), and the multi-arg URI constructor percent-encodes # as %23, producing an incorrect sentryUri path. The queryIndex stripping logic at line 100 needs a similar check for #.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit cacc249. Configure here.
| } else { | ||
| host = hostPort.substring(0, portColon); | ||
| port = Integer.parseInt(hostPort.substring(portColon + 1)); | ||
| } |
There was a problem hiding this comment.
IPv6 host parsing broken by first-colon port detection
Low Severity
hostPort.indexOf(':') finds the first colon, which for IPv6 literals like [::1] or [::1]:9000 matches a colon inside the brackets rather than the port separator. This causes host to be [ and Integer.parseInt to throw on the remaining garbage. The old java.net.URI parser handled IPv6 bracket syntax correctly. Self-hosted Sentry users with IPv6 addresses would be unable to initialize the SDK.
Reviewed by Cursor Bugbot for commit cacc249. Configure here.


Summary
new URI(dsnString).normalize()in theDsnconstructor with manualindexOf/substringparsing to avoid the slowjava.net.URIparser on AndroidretrieveParsedDsn()is called on the main thread duringSentry.init()→preInitConfigurations(), so this directly impacts app startup timeURIconstruction is from pre-parsed components (new URI(scheme, null, host, port, path, null, null)), which is much cheaper since it doesn't re-parse a stringRelates to: https://linear.app/getsentry/issue/JAVA-516/move-dsn-parsing-off-the-main-thread-during-init
🤖 Generated with Claude Code