Skip to content
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

perf(libs/json): Lower heap overhead of JSON encoding (backport #2846… #29

Merged
merged 3 commits into from
Apr 30, 2024

Conversation

czarcas7ic
Copy link
Member

…) (cometbft#2876)


Many RPC methods require JSON marshalled responses. We saw this taking a notable amount of heap allocation in query serving full nodes. This PR removes some extra heap allocations that were being done. We avoided using the more efficient encoder.Encode before, because it added a newline. This PR changes the function signature for these private methods to be using *bytes.Buffer, and then uses the in-buffer methods (rather than a second copy). We then just truncate the final byte after each such call, which does not waste any allocations.

I added a benchmark for the most complex test case.

OLD:

BenchmarkJsonMarshalStruct-12              78992             15542 ns/op            4487 B/op        191 allocs/op

New:

BenchmarkJsonMarshalStruct-12              93346             11132 ns/op            3245 B/op         58 allocs/op

Roughly a 3-4x reduction in the number of allocations, and 20% speedup.



PR checklist

  • Tests written/updated
  • Changelog entry added in .changelog (we use unclog to manage our changelog)
  • Updated relevant documentation (docs/ or spec/) and code comments

…bft#2846) (cometbft#2876)

---

Many RPC methods require JSON marshalled responses. We saw this taking a
notable amount of heap allocation in query serving full nodes. This PR
removes some extra heap allocations that were being done. We avoided
using the more efficient encoder.Encode before, because it added a
newline. This PR changes the function signature for these private
methods to be using *bytes.Buffer, and then uses the in-buffer methods
(rather than a second copy). We then just truncate the final byte after
each such call, which does not waste any allocations.

I added a benchmark for the most complex test case.

OLD:
```
BenchmarkJsonMarshalStruct-12              78992             15542 ns/op            4487 B/op        191 allocs/op
```
New:
```
BenchmarkJsonMarshalStruct-12              93346             11132 ns/op            3245 B/op         58 allocs/op
```

Roughly a 3-4x reduction in the number of allocations, and 20% speedup.

- [x] Tests written/updated - Existing tests cover this
- [x] Changelog entry added in `.changelog` (we use
[unclog](https://github.com/informalsystems/unclog) to manage our
changelog)
- [x] Updated relevant documentation (`docs/` or `spec/`) and code
comments
- [x] Title follows the [Conventional
Commits](https://www.conventionalcommits.org/en/v1.0.0/) spec
<hr>This is an automatic backport of pull request cometbft#2846 done by
[Mergify](https://mergify.com).

---------

Co-authored-by: Dev Ojha <[email protected]>
Co-authored-by: Andy Nogueira <[email protected]>
@czarcas7ic czarcas7ic added the S:backport/v24 backport to the osmo-v24/v0.37.4 branch label Apr 29, 2024
@czarcas7ic czarcas7ic marked this pull request as ready for review April 29, 2024 17:25
@czarcas7ic czarcas7ic merged commit ee66963 into osmo/v0.37.4 Apr 30, 2024
3 of 16 checks passed
mergify bot pushed a commit that referenced this pull request Apr 30, 2024
…bft#2846… (#29)

* perf(libs/json): Lower heap overhead of JSON encoding (backport cometbft#2846) (cometbft#2876)

---

Many RPC methods require JSON marshalled responses. We saw this taking a
notable amount of heap allocation in query serving full nodes. This PR
removes some extra heap allocations that were being done. We avoided
using the more efficient encoder.Encode before, because it added a
newline. This PR changes the function signature for these private
methods to be using *bytes.Buffer, and then uses the in-buffer methods
(rather than a second copy). We then just truncate the final byte after
each such call, which does not waste any allocations.

I added a benchmark for the most complex test case.

OLD:
```
BenchmarkJsonMarshalStruct-12              78992             15542 ns/op            4487 B/op        191 allocs/op
```
New:
```
BenchmarkJsonMarshalStruct-12              93346             11132 ns/op            3245 B/op         58 allocs/op
```

Roughly a 3-4x reduction in the number of allocations, and 20% speedup.

- [x] Tests written/updated - Existing tests cover this
- [x] Changelog entry added in `.changelog` (we use
[unclog](https://github.com/informalsystems/unclog) to manage our
changelog)
- [x] Updated relevant documentation (`docs/` or `spec/`) and code
comments
- [x] Title follows the [Conventional
Commits](https://www.conventionalcommits.org/en/v1.0.0/) spec
<hr>This is an automatic backport of pull request cometbft#2846 done by
[Mergify](https://mergify.com).

---------

Co-authored-by: Dev Ojha <[email protected]>
Co-authored-by: Andy Nogueira <[email protected]>

* changelog

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Dev Ojha <[email protected]>
Co-authored-by: Andy Nogueira <[email protected]>
(cherry picked from commit ee66963)
czarcas7ic added a commit that referenced this pull request Apr 30, 2024
…bft#2846… (#29) (#33)

* perf(libs/json): Lower heap overhead of JSON encoding (backport cometbft#2846) (cometbft#2876)

---

Many RPC methods require JSON marshalled responses. We saw this taking a
notable amount of heap allocation in query serving full nodes. This PR
removes some extra heap allocations that were being done. We avoided
using the more efficient encoder.Encode before, because it added a
newline. This PR changes the function signature for these private
methods to be using *bytes.Buffer, and then uses the in-buffer methods
(rather than a second copy). We then just truncate the final byte after
each such call, which does not waste any allocations.

I added a benchmark for the most complex test case.

OLD:
```
BenchmarkJsonMarshalStruct-12              78992             15542 ns/op            4487 B/op        191 allocs/op
```
New:
```
BenchmarkJsonMarshalStruct-12              93346             11132 ns/op            3245 B/op         58 allocs/op
```

Roughly a 3-4x reduction in the number of allocations, and 20% speedup.

- [x] Tests written/updated - Existing tests cover this
- [x] Changelog entry added in `.changelog` (we use
[unclog](https://github.com/informalsystems/unclog) to manage our
changelog)
- [x] Updated relevant documentation (`docs/` or `spec/`) and code
comments
- [x] Title follows the [Conventional
Commits](https://www.conventionalcommits.org/en/v1.0.0/) spec
<hr>This is an automatic backport of pull request cometbft#2846 done by
[Mergify](https://mergify.com).

---------

Co-authored-by: Dev Ojha <[email protected]>
Co-authored-by: Andy Nogueira <[email protected]>

* changelog

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Dev Ojha <[email protected]>
Co-authored-by: Andy Nogueira <[email protected]>
(cherry picked from commit ee66963)

Co-authored-by: Adam Tucker <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S:backport/v24 backport to the osmo-v24/v0.37.4 branch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant