Skip to content

Avoid unnecessary String allocations in AstPrinter #3710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 7, 2024

Conversation

kilink
Copy link
Contributor

@kilink kilink commented Sep 22, 2024

Avoid the overhead of allocating unnecessary intermediate String instances in AstPrinter by only appending to the supplied StringBuilder. When running the AstPrinterBenchmark with the gc profiler, this significantly reduces the allocation rate:

before:

gc.alloc.rate: 4846.634 MB/sec
gc.alloc.rate.norm: 86960.001 B/op

after:

gc.alloc.rate: 2524.634 MB/sec
gc.alloc.rate.norm: 10432.000 B/op

The benchmarks also show a doubling in throughput.

Avoid the overhead of allocating unnecessary intermediate String instances in AstPrinter
by only appending to the supplied StringBuilder. When running the AstPrinterBenchmark with
the gc profiler, this significantly reduces the allocation rate:

before:

gc.alloc.rate:      4846.634 MB/sec
gc.alloc.rate.norm: 86960.001 B/op

after:

gc.alloc.rate:      2524.634 MB/sec
gc.alloc.rate.norm: 10432.000 B/op

The benchmarks also show a doubling in throughput.
StringBuilder sb = new StringBuilder(stringValue.length());
escapeJsonStringTo(sb, stringValue);
return sb.toString();
}
Copy link
Member

Choose a reason for hiding this comment

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

Nice one

@bbakerman
Copy link
Member

Thanks for this PR - it makes a lot of sense to pass in the one StringBuilder - this code was originally ported from graphql-js I think and hence it would have inherited its string appending approach.

Out of interest, what hot spot did you have such that you call AstPrinter a lot? ie what prompted you to optimise this code?

I ask to try and gauge how likely this is to benefit the wider community

Copy link
Member

@bbakerman bbakerman left a comment

Choose a reason for hiding this comment

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

AstPrinter has lots of tests so making this kinda of change is much safer

@bbakerman bbakerman added this to the 23.x breaking changes milestone Sep 22, 2024
@bbakerman bbakerman added the performance work that is primarily targeted as performance improvements label Sep 22, 2024
@kilink
Copy link
Contributor Author

kilink commented Sep 23, 2024

Out of interest, what hot spot did you have such that you call AstPrinter a lot? ie what prompted you to optimise this code?

I'll confess I don't 100% understand the use case, but while looking at performance of an internal app involved in federation, I noticed they had written their own custom printer for a subset of Node types to avoid the overhead of the graphql-java AstPrinter. I thought I'd improve AstPrinter itself so such workarounds wouldn't be necessary.

If this change looks good to you all then I'd like to follow up with some API additions to allow passing in an Appendable / StringBuilder to the print methods, which also allows callers to re-use StringBuilder instances.

@dondonz
Copy link
Member

dondonz commented Sep 24, 2024

Thanks so much for contributing these changes. It's cool to see how these improvements matter at scale!

If this change looks good to you all then I'd like to follow up with some API additions to allow passing in an Appendable / StringBuilder to the print methods, which also allows callers to re-use StringBuilder instances.

Please do keep the PRs coming!

@dondonz dondonz added this pull request to the merge queue Nov 7, 2024
Merged via the queue into graphql-java:master with commit cbfef8a Nov 7, 2024
1 check passed
@kilink kilink deleted the astprinter-alloc-optimization branch January 23, 2025 17:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance work that is primarily targeted as performance improvements
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants