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

x509: reduce allocations for wrap_in_sequence #1563

Merged
merged 1 commit into from
Nov 6, 2023
Merged

Conversation

jsha
Copy link
Contributor

@jsha jsha commented Nov 2, 2023

Instead of taking a Vec<u8> and inserting bytes at the beginning, take a &[u8] and return a new vector containing those bytes plus a tag and a length.

This isn't the perfect approach for all situations, but for one of the main places we call wrap_in_sequence (DistinguishedName::in_sequence), it's optimal because the input is &[u8], meaning we can't write to a previously existing Vec<u8> (which would potentially save allocations by using excess capacity at the end of the Vec).

In the process, change the one call site for wrap_in_asn1_len to call the new asn1_wrap function instead, which encodes a tag and length at the same time, reducing reallocations and copies.

This has a slight secondary benefit: the resulting Vec is exactly sized to what it holds, instead of following the doubling approach and possibly over-allocating. This saves a handful of bytes in a long-lived data structure.

Fixes #1562

Copy link

codecov bot commented Nov 2, 2023

Codecov Report

Merging #1563 (5170fca) into main (b776a57) will increase coverage by 0.00%.
Report is 1 commits behind head on main.
The diff coverage is 100.00%.

@@           Coverage Diff           @@
##             main    #1563   +/-   ##
=======================================
  Coverage   96.41%   96.41%           
=======================================
  Files          75       75           
  Lines       15524    15525    +1     
=======================================
+ Hits        14968    14969    +1     
  Misses        556      556           
Files Coverage Δ
rustls/src/crypto/ring/sign.rs 96.86% <100.00%> (-0.06%) ⬇️
rustls/src/msgs/handshake.rs 98.10% <100.00%> (-0.01%) ⬇️
rustls/src/x509.rs 100.00% <100.00%> (ø)

📣 Codecov offers a browser extension for seamless coverage viewing on GitHub. Try it in Chrome or Firefox today!

Copy link
Member

@cpu cpu left a comment

Choose a reason for hiding this comment

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

Nice! Looks good to me.

Since this was a fix for a perf related issue it would be interesting to know if a tool like https://github.com/KDE/heaptrack shows the expected improvement under profiling.

rustls/src/x509.rs Outdated Show resolved Hide resolved
rustls/src/crypto/ring/sign.rs Outdated Show resolved Hide resolved
Instead of taking a `Vec<u8>` and inserting bytes at the beginning,
take a `&[u8]` and return a new vector containing those bytes plus
a tag and a length.

This isn't the perfect approach for all situations, but for one of the
main places we call wrap_in_sequence (DistinguishedName::in_sequence),
it's optimal because the input is `&[u8]`, meaning we can't write to
a previously existing `Vec<u8>` (which would potentially save
allocations by using excess capacity at the end of the Vec).

In the process, change the one call site for `wrap_in_asn1_len` to call
the new `asn1_wrap` function instead, which encodes a tag and length at
the same time, reducing reallocations and copies.

This has a slight secondary benefit: the resulting Vec is exactly sized
to what it holds, instead of following the doubling approach and
possibly over-allocating. This saves a handful of bytes in a long-lived
data structure.
@jsha
Copy link
Contributor Author

jsha commented Nov 4, 2023

Pushed fixes.

Since this was a fix for a perf related issue it would be interesting to know if a tool like https://github.com/KDE/heaptrack shows the expected improvement under profiling.

I can take a look at this. Might take me a minute to get heaptrack set up.

@jsha
Copy link
Contributor Author

jsha commented Nov 4, 2023

On main:

heaptrack ./target/release/simpleclient
...
heaptrack stats:
        allocations:            380
        leaked allocations:     30
        temporary allocations:  102

On this branch:

heaptrack ./target/release/simpleclient
...
heaptrack stats:
        allocations:            372
        leaked allocations:     30
        temporary allocations:  98

Copy link
Member

@djc djc left a comment

Choose a reason for hiding this comment

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

Nice!

@cpu
Copy link
Member

cpu commented Nov 6, 2023

This feels small enough in scope that we can merge it without waiting on Ctz to be back.

@cpu cpu enabled auto-merge November 6, 2023 13:35
@cpu cpu added this pull request to the merge queue Nov 6, 2023
Merged via the queue into rustls:main with commit 22a3583 Nov 6, 2023
23 checks passed
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.

x509: heap allocation hotspot in ASN1-wrapping logic
3 participants