Skip to content

perf: introduce ToBytes in bls.h and use it in all spots trivially possible, convert vecBytes to std::array#6515

Merged
PastaPastaPasta merged 4 commits into
dashpay:developfrom
PastaPastaPasta:refac-bls-stackify
Jan 29, 2025
Merged

perf: introduce ToBytes in bls.h and use it in all spots trivially possible, convert vecBytes to std::array#6515
PastaPastaPasta merged 4 commits into
dashpay:developfrom
PastaPastaPasta:refac-bls-stackify

Conversation

@PastaPastaPasta
Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

we made changes to bls library library to allow std::array based serialization, which resulted in ~10% speedups in serialization in library benchmarks. I noticed today:

pre-this change:
Pasted Graphic

post this change:
Pasted Graphic 1

this shows that roughly 2.5% of total cycles during reindex are spent on vector new in our bls.h object.

What was done?

Convert to array to avoid dynamic allocation slowdown

How Has This Been Tested?

reindexing atm, looks good so far, and performance is improved as expected

Breaking Changes

None

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

@PastaPastaPasta PastaPastaPasta added this to the 22.1 milestone Dec 29, 2024
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 29, 2024

Removed to simplify merge commit message

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/llmq/dkgsession.cpp (1)

1024-1026: Consistency for quorumSig manipulation.
The approach parallels the previous signature manipulation, ensuring ToBytes and SetBytes remain consistent for simulation.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6310321 and d350cbc37ed75995024494cc328f766a427c9907.

📒 Files selected for processing (4)
  • src/bls/bls.h (14 hunks)
  • src/governance/object.cpp (1 hunks)
  • src/governance/vote.cpp (1 hunks)
  • src/llmq/dkgsession.cpp (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/governance/object.cpp
🔇 Additional comments (17)
src/governance/vote.cpp (1)

185-185: Use of SetBytes is consistent and appropriate.
This change keeps the code aligned with the new SetBytes approach for handling BLS data.

src/bls/bls.h (15)

62-62: Consistent invocation of SetBytes.
Using SetBytes in the constructor keeps object creation unified with the broader rename from SetByteVector.


Line range hint 106-119: Ensure proper reset on invalid input.
The new SetBytes method correctly resets the wrapper on short or zero-filled input, preventing malformed states.


139-147: Addition of ToBytes methods is a welcome change.
Returning a fixed-size std::array helps eliminate unnecessary dynamic allocations, improving performance.


167-167: Maintain uniform usage of SetBytes.
Replacing direct references to old methods ensures that all code paths use SetBytes consistently.


179-179: Directly writing array bytes is clear.
Using AsBytes with the result of ToBytes is straightforward for serialization.


193-193: De-serialize using SetBytes.
Switching from SetByteVector to SetBytes for reading from streams keeps the routine consistent with the rest of the refactoring.


198-198: Fallback scheme usage is correct.
Attempting the opposite scheme if the first attempt fails is well-handled here, continuing to rely on SetBytes.


218-218: Efficient verification using memcmp.
Comparing the byte arrays via memcmp ensures a direct check of the internal representation for malleability.


234-234: Hex conversion uses ToBytes effectively.
Extracting bytes for hex-string output further demonstrates the benefit of a fixed-size array.


261-264: Fixed-size array in CBLSIdImplicit.
Returning a std::array<uint8_t, 32> for serialization is consistent with the rest of the new design.


397-397: Refactor to fixed-size vecBytes.
Changing from std::vector<uint8_t> to std::array<uint8_t, BLSObject::SerSize> reduces dynamic allocations in CBLSLazyWrapper.


408-408: Default initialization for vecBytes.
Initializing the array with {0} ensures deterministic behavior for an uninitialized buffer.


450-450: Rebuilding vecBytes from ToBytes.
Writing the new array in Serialize is correct and locks in a consistent internal representation.


498-498: Correct use of obj.SetBytes after retrieval.
Deserializing data from vecBytes continues the consistent usage pattern of the new API.


535-535: ToBytes usage in GetHash.
Generating the hash directly from a fixed-size array clarifies the logic and prevents memory reallocation overhead.

src/llmq/dkgsession.cpp (1)

1019-1021: Properly modifying the in-flight signature bytes.
This simulated "lie" operation showcases the flexible usage of ToBytes/SetBytes, but verify that offset [5] is always valid.

@knst
Copy link
Copy Markdown
Collaborator

knst commented Dec 29, 2024

it conflicts with my PR #6508 which already had one review iteration by Udjin.
Consider reviewing 6508 and rebase this PR on top.

@PastaPastaPasta PastaPastaPasta marked this pull request as draft January 7, 2025 05:44
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 7, 2025

This pull request has conflicts, please rebase.

…ssible, convert vecBytes to std::array

this results in an improved reindex speed as previously roughly 2% of total cycles were just in allocating the vector.
@PastaPastaPasta PastaPastaPasta marked this pull request as ready for review January 27, 2025 05:45
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/bls/bls.h (1)

Line range hint 1-591: Excellent performance optimization through stack allocation.

The conversion from std::vector to std::array for serialization is a well-executed performance improvement that:

  1. Eliminates heap allocations
  2. Maintains thread safety
  3. Preserves backward compatibility
  4. Introduces no breaking changes

The changes align perfectly with the PR's objective of improving serialization performance.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d350cbc37ed75995024494cc328f766a427c9907 and 8510351.

📒 Files selected for processing (4)
  • src/bls/bls.h (15 hunks)
  • src/governance/object.cpp (1 hunks)
  • src/governance/vote.cpp (1 hunks)
  • src/llmq/dkgsession.cpp (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/governance/vote.cpp
  • src/governance/object.cpp
  • src/llmq/dkgsession.cpp
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Build (linux64_sqlite, x86_64-pc-linux-gnu, linux64)
  • GitHub Check: Build (linux64_nowallet, x86_64-pc-linux-gnu, linux64)
  • GitHub Check: Build (linux64_fuzz, x86_64-pc-linux-gnu, linux64)
  • GitHub Check: Build (linux64_cxx20, x86_64-pc-linux-gnu, linux64)
  • GitHub Check: Build (arm-linux, arm-linux-gnueabihf, arm-linux)
🔇 Additional comments (5)
src/bls/bls.h (5)

130-133: LGTM! Performance improvement through stack allocation.

The new ToBytes method efficiently returns a fixed-size array, eliminating heap allocations during serialization.


243-243: LGTM! Efficient serialization using underlying data.

Good use of [[nodiscard]] attribute and direct member access for zero-copy serialization.


441-444: LGTM! Thread-safe serialization update.

The serialization code correctly handles the transition to array-based storage while maintaining thread safety through mutex protection.


271-271: LGTM! Consistent usage across derived classes.

The derived classes correctly use the new SetBytes method while maintaining backward compatibility through the legacy scheme parameter.

Also applies to: 343-343


Line range hint 388-400: Consider adding size validation in constructor.

While changing vecBytes to std::array improves performance, consider adding a static_assert to validate BLSObject::SerSize matches the expected sizes defined in the constants.

Comment thread src/bls/bls.h Outdated
inline void Serialize(Stream& s, const bool specificLegacyScheme) const
{
s.write(AsBytes(Span{ToByteVector(specificLegacyScheme).data(), SerSize}));
s.write(AsBytes(Span{ToBytes(specificLegacyScheme).data(), SerSize}));
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

here's UB: ToBytes returns temporary object and Span doesn't own it.

Suggested change
s.write(AsBytes(Span{ToBytes(specificLegacyScheme).data(), SerSize}));
const auto bytes{ToBytes(specificLegacyScheme)};
s.write(AsBytes(Span{bytes.data(), SerSize}));

Comment thread src/bls/bls.h Outdated
inline bool CheckMalleable(Span<uint8_t> vecBytes, const bool specificLegacyScheme) const
{
if (memcmp(vecBytes.data(), ToByteVector(specificLegacyScheme).data(), SerSize)) {
if (memcmp(vecBytes.data(), ToBytes(specificLegacyScheme).data(), SerSize)) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

here's UB. after call data() temporary object is erased.

Suggested change
if (memcmp(vecBytes.data(), ToBytes(specificLegacyScheme).data(), SerSize)) {
const auto bytes{ToBytes(specificLegacyScheme)};
if (memcmp(vecBytes.data(), bytes.data(), SerSize)) {

Comment thread src/bls/bls.h Outdated
CBLSLazyWrapper() :
vecBytes(BLSObject::SerSize, 0),
bufLegacyScheme(bls::bls_legacy_scheme.load())
vecBytes{0},
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: Should be changed to avoid confusion

Suggested change
vecBytes{0},
vecBytes{},

Comment thread src/bls/bls.h

std::array<uint8_t, SerSize> ToBytes(const bool specificLegacyScheme) const
{
return impl.SerializeToArray(specificLegacyScheme);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
return impl.SerializeToArray(specificLegacyScheme);
if (!fValid) {
return std::array<uint8_t, SerSize>{};
}
return impl.SerializeToArray(specificLegacyScheme);

it works for me with this fix 5b4b333

Copy link
Copy Markdown
Collaborator

@knst knst left a comment

Choose a reason for hiding this comment

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

utACK 2ca49da

Copy link
Copy Markdown

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

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

utACK 2ca49da

Copy link
Copy Markdown
Collaborator

@kwvg kwvg left a comment

Choose a reason for hiding this comment

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

utACK 2ca49da

@PastaPastaPasta PastaPastaPasta merged commit cd8f1d0 into dashpay:develop Jan 29, 2025
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.

4 participants