Skip to content

Conversation

@schlosna
Copy link
Contributor

@schlosna schlosna commented Jul 14, 2022

Before this PR

com.palantir.conjure.java.api.config.service.UserAgents#isValidVersion is frequently used to validate the user agent version string, and currently uses an expensive regex which does a bunch of allocations and expensive processing. This generates unnecessary garbage and CPU cycles for services handling high volumes of HTTP requests.

image
image

After this PR

We can use a hand rolled parser borrowed and simplified from palantir/sls-version-java#463 to validate UserAgent version strings up to 4 groups (commonly used by browsers).

==COMMIT_MSG==
Optimize UserAgent version validation
==COMMIT_MSG==

Possible downsides?

Duplicates code locally from https://github.com/palantir/sls-version-java because browser version strings don't conform to SLS versioning.

@changelog-app
Copy link

changelog-app bot commented Jul 14, 2022

Generate changelog in changelog/@unreleased

Type
See change types. Select one:

  • Feature
  • Improvement
  • Fix
  • Break
  • Deprecation
  • Manual task
  • Migration

Description

Optimize UserAgent version validation

Check the box to generate changelog(s)

  • Generate changelog entry

Arguments.of("1.2.3-4-gabc", -1, true),
Arguments.of("1.2.3.4-rc5-6-gabc", -1, true),
Arguments.of("1.2.3-4", -1, false),
Arguments.of("0-0-0", -1, false));
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be helpful to add some test data with multi-digit numeric components e.g. 123.456.789 and 123.456.789-rc0

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added a few more

* because primitive longs live on the stack and don't impact GC.
*/
@Immutable
final class VersionParser {
Copy link
Contributor

Choose a reason for hiding this comment

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

Fantastic documentation, code is also very readable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines +43 to +44
for (int i = 1; getIndex(state) < string.length(); i++) {
state = number(string, getIndex(state));
Copy link
Contributor

Choose a reason for hiding this comment

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

We could probably dedup out repeated calls to getIndex(state) in places that state doesn't change, however it's a trivial operation and likely not worth deconstructing the loop

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I'm going to leave it as-is for now. Deduping the getIndex for loop condition & first use doesn't really change benchmark, so going to opt for simplicity and consistent use of getIndex(state)

@schlosna
Copy link
Contributor Author

Added some benchmarks comparing the custom parser validation to regex validation and the custom parser is ~3x faster for common cases than regex fallback.

Apple M1 Pro, JDK 17.0.3, OpenJDK 64-Bit Server VM, 17.0.3+7-LTS
Benchmark                                    (version)  Mode  Cnt  Score    Error  Units
VersionParserBenchmark.isValid             123.456.789  avgt    3  0.030 ±  0.001  us/op
VersionParserBenchmark.isValid  12.34.56.78-rc9-0-gabc  avgt    3  0.144 ±  0.005  us/op
VersionParserBenchmark.parser              123.456.789  avgt    3  0.030 ±  0.001  us/op
VersionParserBenchmark.parser   12.34.56.78-rc9-0-gabc  avgt    3  0.035 ±  0.001  us/op
VersionParserBenchmark.regex               123.456.789  avgt    3  0.100 ±  0.004  us/op
VersionParserBenchmark.regex    12.34.56.78-rc9-0-gabc  avgt    3  0.117 ±  0.003  us/op

@bulldozer-bot bulldozer-bot bot merged commit 3719db9 into develop Jul 15, 2022
@bulldozer-bot bulldozer-bot bot deleted the ds/versions branch July 15, 2022 16:07
@svc-autorelease
Copy link
Collaborator

Released 2.26.0

@schlosna schlosna mentioned this pull request Jul 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants