Skip to content

Commit

Permalink
fix: no memory allocation in StableContainer Profile hashTreeRootInto()
Browse files Browse the repository at this point in the history
  • Loading branch information
twoeths committed Oct 14, 2024
1 parent f17019e commit 79152c4
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 13 deletions.
1 change: 1 addition & 0 deletions packages/ssz/src/type/composite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ export abstract class CompositeType<V, TV, TVDU> extends Type<V> {
const merkleBytes = this.getChunkBytes(value);
merkleizeInto(merkleBytes, this.maxChunkCount, output, offset);
if (this.cachePermanentRootStruct) {
// Buffer.prototype.slice does not copy memory, Enforce Uint8Array usage https://github.com/nodejs/node/issues/28087
const cachedRoot = Uint8Array.prototype.slice.call(output, offset, offset + 32);
(value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = cachedRoot;
}
Expand Down
7 changes: 6 additions & 1 deletion packages/ssz/src/type/listComposite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,12 @@ export class ListCompositeType<
merkleizeInto(this.mixInLengthChunkBytes, chunkCount, output, offset);

if (this.cachePermanentRootStruct) {
(value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = output.slice(offset, offset + 32);
// Buffer.prototype.slice does not copy memory, Enforce Uint8Array usage https://github.com/nodejs/node/issues/28087
(value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = Uint8Array.prototype.slice.call(
output,
offset,
offset + 32
);
}
}

Expand Down
11 changes: 5 additions & 6 deletions packages/ssz/src/type/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import {Case} from "../util/strings";
import {BitArray} from "../value/bitArray";
import {mixInActiveFields, setActiveFields} from "./stableContainer";
import {NonOptionalFields, isOptionalType, toNonOptionalType} from "./optional";
import {allocUnsafe} from "@chainsafe/as-sha256";
/* eslint-disable @typescript-eslint/member-ordering */

type BytesRange = {start: number; end: number};
Expand Down Expand Up @@ -89,6 +88,8 @@ export class ProfileType<Fields extends Record<string, Type<unknown>>> extends C
protected readonly TreeView: ContainerTreeViewTypeConstructor<Fields>;
protected readonly TreeViewDU: ContainerTreeViewDUTypeConstructor<Fields>;
private optionalFieldsCount: number;
// temporary root to avoid memory allocation
private tempRoot = new Uint8Array(32);

constructor(readonly fields: Fields, activeFields: BitArray, readonly opts?: ProfileOptions<Fields>) {
super();
Expand Down Expand Up @@ -378,13 +379,11 @@ export class ProfileType<Fields extends Record<string, Type<unknown>>> extends C
}

const merkleBytes = this.getChunkBytes(value);
const root = allocUnsafe(32);
merkleizeInto(merkleBytes, this.maxChunkCount, root, 0);
mixInActiveFields(root, this.activeFields, root, 0);
output.set(root, offset);
merkleizeInto(merkleBytes, this.maxChunkCount, this.tempRoot, 0);
mixInActiveFields(this.tempRoot, this.activeFields, output, offset);

if (this.cachePermanentRootStruct) {
(value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = root;
(value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = this.tempRoot.slice();
}
}

Expand Down
11 changes: 5 additions & 6 deletions packages/ssz/src/type/stableContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import {
import {Case} from "../util/strings";
import {isOptionalType, toNonOptionalType, NonOptionalFields} from "./optional";
import {BitArray} from "../value/bitArray";
import {allocUnsafe} from "@chainsafe/as-sha256";
/* eslint-disable @typescript-eslint/member-ordering */

type BytesRange = {start: number; end: number};
Expand Down Expand Up @@ -94,6 +93,8 @@ export class StableContainerType<Fields extends Record<string, Type<unknown>>> e
protected readonly TreeView: ContainerTreeViewTypeConstructor<Fields>;
protected readonly TreeViewDU: ContainerTreeViewDUTypeConstructor<Fields>;
private padActiveFields: boolean[];
// temporary root to avoid memory allocation
private tempRoot = new Uint8Array(32);

constructor(fields: Fields, readonly maxFields: number, readonly opts?: StableContainerOptions<Fields>) {
super();
Expand Down Expand Up @@ -351,18 +352,16 @@ export class StableContainerType<Fields extends Record<string, Type<unknown>>> e
}

const merkleBytes = this.getChunkBytes(value);
const root = allocUnsafe(32);
merkleizeInto(merkleBytes, this.maxChunkCount, root, 0);
merkleizeInto(merkleBytes, this.maxChunkCount, this.tempRoot, 0);
// compute active field bitvector
const activeFields = BitArray.fromBoolArray([
...this.fieldsEntries.map(({fieldName}) => value[fieldName] != null),
...this.padActiveFields,
]);
mixInActiveFields(root, activeFields, root, 0);
output.set(root, offset);
mixInActiveFields(this.tempRoot, activeFields, output, offset);

if (this.cachePermanentRootStruct) {
(value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = root;
(value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = this.tempRoot.slice();
}
}

Expand Down

0 comments on commit 79152c4

Please sign in to comment.