-
-
Notifications
You must be signed in to change notification settings - Fork 21
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
feat: improve type.hashTreeRoot() using batch #409
base: master
Are you sure you want to change the base?
Conversation
Performance Report✔️ no performance regression detected Full benchmark results
|
tested this on |
sha256 works in blocks, each is 64 bytes so perhaps it's more meaningful to reflect that for also with holesky, there are 1.7M validators. For every 8 deposits we have to reallocate the whole 1.7M * 8 bytes = 13.6MB for Update:
|
9e32c5c
to
7ed3ced
Compare
d3821ee
to
cbb30a2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a few comments but I think this PR really needs to be reviewed by @wemeetagain
// Merkleization | ||
|
||
protected getRoots(value: ByteArray): Uint8Array[] { | ||
return splitIntoRootChunks(value); | ||
protected getBlocksBytes(value: ByteArray): Uint8Array { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Im confused by what BlocksBytes
represents. I understand there is a shared buffer that is getting reused but why the name Blocks
and thus bytes of a block? Perhaps we can talk about the naming conventions here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like a Block
is the unit used for (2) 32-byte roots?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps calling 32 byte chunks Bytes32
and 64-byte "blocks" Bytes64
? Not sure, what do you think?
|
||
blocksBuffer.set(value); | ||
const valueLen = value.length; | ||
const blockByteLen = Math.ceil(valueLen / 64) * 64; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be helpful to break out a helper function so its clear why this is happening everywhere.
export function getPaddedByte32Count(buf: ArrayBuffer): number {
return Math.ceil(buf.length / 32);
}
export function getPaddedByte64Count(buf: ArrayBuffer): number {
return Math.ceil(buf.length / 64);
}
const blockDiff = newBlockCount - oldBlockCount; | ||
const newBlocksBytes = new Uint8Array(blockDiff * 64); | ||
for (let i = 0; i < blockDiff; i++) { | ||
this.blockArray.push(newBlocksBytes.subarray(i * 64, (i + 1) * 64)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why loop and push in chunks? Why not just push all at once and only trigger one resize to the blockArray
?
Motivation
Description
getRoots()
and compute root from there, this PR implementgetChunkBytes()
merkleizeInto()
which use batch therechunkBytesBuffer
memory in type, almost noUint8Array
allocations in the middlehashTreeRootInto()
api. This is needed in case consumers want to reuse memory allocation thereallocUnsafe()
of as-sha256 where it makes sensecherry picked from #378