Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions yarn-project/circuit-types/src/stats/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,24 +151,72 @@ export const Metrics = [
description: 'Time to insert a batch of leaves into an append-only tree',
events: ['tree-insertion'],
},
{
name: 'batch_insert_into_append_only_tree_16_depth_hash_count',
groupBy: 'leaf-count',
description: 'The number of hashes necessary to insert a batch of leaves into',
events: ['tree-insertion'],
},
{
name: 'batch_insert_into_append_only_tree_16_depth_hash_ms',
groupBy: 'leaf-count',
description: 'Average duration for a hash operation',
events: ['tree-insertion'],
},
{
name: 'batch_insert_into_append_only_tree_32_depth_ms',
groupBy: 'leaf-count',
description: 'Time to insert a batch of leaves into an append-only tree',
events: ['tree-insertion'],
},
{
name: 'batch_insert_into_append_only_tree_32_depth_hash_count',
groupBy: 'leaf-count',
description: 'The number of hashes necessary to insert a batch of leaves into',
events: ['tree-insertion'],
},
{
name: 'batch_insert_into_append_only_tree_32_depth_hash_ms',
groupBy: 'leaf-count',
description: 'Average duration for a hash operation',
events: ['tree-insertion'],
},
{
name: 'batch_insert_into_indexed_tree_20_depth_ms',
groupBy: 'leaf-count',
description: 'Time to insert a batch of leaves into an indexed tree',
events: ['tree-insertion'],
},
{
name: 'batch_insert_into_indexed_tree_20_depth_hash_count',
groupBy: 'leaf-count',
description: 'The number of hashes necessary to insert a batch of leaves into',
events: ['tree-insertion'],
},
{
name: 'batch_insert_into_indexed_tree_20_depth_hash_ms',
groupBy: 'leaf-count',
description: 'Average duration for a hash operation',
events: ['tree-insertion'],
},
{
name: 'batch_insert_into_indexed_tree_40_depth_ms',
groupBy: 'leaf-count',
description: 'Time to insert a batch of leaves into an indexed tree',
events: ['tree-insertion'],
},
{
name: 'batch_insert_into_indexed_tree_40_depth_hash_count',
groupBy: 'leaf-count',
description: 'The number of hashes necessary to insert a batch of leaves into',
events: ['tree-insertion'],
},
{
name: 'batch_insert_into_indexed_tree_40_depth_hash_ms',
groupBy: 'leaf-count',
description: 'Average duration for a hash operation',
events: ['tree-insertion'],
},
] as const satisfies readonly Metric[];

/** Metric definitions to track from benchmarks. */
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/circuit-types/src/stats/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ export type TreeInsertionStats = {
treeDepth: number;
/** Tree type */
treeType: 'append-only' | 'indexed';
/** Number of hashes performed */
hashCount: number;
/** Average duration of a hash operation */
hashDuration: number;
};

/** A new tx was added to the tx pool. */
Expand Down
51 changes: 51 additions & 0 deletions yarn-project/merkle-tree/src/hasher_with_stats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Hasher } from '@aztec/types/interfaces';

import { createHistogram, performance } from 'perf_hooks';

/**
* A helper class to track stats for a Hasher
*/
export class HasherWithStats implements Hasher {
hashCount = 0;
hashInputsCount = 0;
hashHistogram = createHistogram();
hashInputsHistogram = createHistogram();

hash: Hasher['hash'];
hashInputs: Hasher['hashInputs'];

constructor(hasher: Hasher) {
this.hash = performance.timerify(
(lhs, rhs) => {
this.hashCount++;
return hasher.hash(lhs, rhs);
},
{ histogram: this.hashHistogram },
);
this.hashInputs = performance.timerify(
(inputs: Buffer[]) => {
this.hashInputsCount++;
return hasher.hashInputs(inputs);
},
{ histogram: this.hashInputsHistogram },
);
}

stats() {
return {
hashCount: this.hashCount,
// timerify records in ns, convert to ms
hashDuration: this.hashHistogram.mean / 1e6,
hashInputsCount: this.hashInputsCount,
hashInputsDuration: this.hashInputsHistogram.mean / 1e6,
};
}

reset() {
this.hashCount = 0;
this.hashHistogram.reset();

this.hashInputsCount = 0;
this.hashInputsHistogram.reset();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ export class StandardIndexedTree extends TreeBase implements IndexedTree {
leaves: Buffer[],
subtreeHeight: SubtreeHeight,
): Promise<BatchInsertionResult<TreeHeight, SubtreeSiblingPathHeight>> {
this.hasher.reset();
const timer = new Timer();
const insertedKeys = new Map<bigint, boolean>();
const emptyLowLeafWitness = getEmptyLowLeafWitness(this.getDepth() as TreeHeight, this.leafPreimageFactory);
Expand Down Expand Up @@ -614,6 +615,7 @@ export class StandardIndexedTree extends TreeBase implements IndexedTree {
treeName: this.getName(),
treeDepth: this.getDepth(),
treeType: 'indexed',
...this.hasher.stats(),
} satisfies TreeInsertionStats);

return {
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/merkle-tree/src/standard_tree/standard_tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export class StandardTree extends TreeBase implements AppendOnlyTree {
* @returns Empty promise.
*/
public async appendLeaves(leaves: Buffer[]): Promise<void> {
this.hasher.reset();
const timer = new Timer();
await super.appendLeaves(leaves);
this.log(`Inserted ${leaves.length} leaves into ${this.getName()} tree`, {
Expand All @@ -26,6 +27,7 @@ export class StandardTree extends TreeBase implements AppendOnlyTree {
treeName: this.getName(),
treeDepth: this.getDepth(),
treeType: 'append-only',
...this.hasher.stats(),
} satisfies TreeInsertionStats);
}

Expand Down
7 changes: 6 additions & 1 deletion yarn-project/merkle-tree/src/tree_base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { SiblingPath } from '@aztec/types/membership';

import { LevelUp, LevelUpChain } from 'levelup';

import { HasherWithStats } from './hasher_with_stats.js';
import { MerkleTree } from './interfaces/merkle_tree.js';

const MAX_DEPTH = 254;
Expand Down Expand Up @@ -40,9 +41,11 @@ export abstract class TreeBase implements MerkleTree {
private cache: { [key: string]: Buffer } = {};
protected log: DebugLogger;

protected hasher: HasherWithStats;

public constructor(
protected db: LevelUp,
protected hasher: Hasher,
hasher: Hasher,
private name: string,
private depth: number,
protected size: bigint = 0n,
Expand All @@ -52,6 +55,8 @@ export abstract class TreeBase implements MerkleTree {
throw Error('Invalid depth');
}

this.hasher = new HasherWithStats(hasher);

// Compute the zero values at each layer.
let current = INITIAL_LEAF;
for (let i = depth - 1; i >= 0; --i) {
Expand Down
8 changes: 8 additions & 0 deletions yarn-project/scripts/src/benchmarks/aggregate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,14 +171,22 @@ function processTreeInsertion(entry: TreeInsertionStats, results: BenchmarkColle
if (entry.treeType === 'append-only') {
if (depth === 16) {
append(results, 'batch_insert_into_append_only_tree_16_depth_ms', bucket, entry.duration);
append(results, 'batch_insert_into_append_only_tree_16_depth_hash_count', bucket, entry.hashCount);
append(results, 'batch_insert_into_append_only_tree_16_depth_hash_ms', bucket, entry.hashDuration);
} else if (depth === 32) {
append(results, 'batch_insert_into_append_only_tree_32_depth_ms', bucket, entry.duration);
append(results, 'batch_insert_into_append_only_tree_32_depth_hash_count', bucket, entry.hashCount);
append(results, 'batch_insert_into_append_only_tree_32_depth_hash_ms', bucket, entry.hashDuration);
}
} else if (entry.treeType === 'indexed') {
if (depth === 20) {
append(results, 'batch_insert_into_indexed_tree_20_depth_ms', bucket, entry.duration);
append(results, 'batch_insert_into_indexed_tree_20_depth_hash_count', bucket, entry.hashCount);
append(results, 'batch_insert_into_indexed_tree_20_depth_hash_ms', bucket, entry.hashDuration);
} else if (depth === 40) {
append(results, 'batch_insert_into_indexed_tree_40_depth_ms', bucket, entry.duration);
append(results, 'batch_insert_into_indexed_tree_40_depth_hash_count', bucket, entry.hashCount);
append(results, 'batch_insert_into_indexed_tree_40_depth_hash_ms', bucket, entry.hashDuration);
}
}
}
Expand Down