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

feat: prover metrics #6050

Merged
merged 1 commit into from
May 2, 2024
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
18 changes: 18 additions & 0 deletions yarn-project/circuit-types/src/stats/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,18 @@ export const Metrics = [
description: 'Time to run a circuit simulation.',
events: ['circuit-simulation'],
},
{
name: 'circuit_witness_generation_time_in_ms',
groupBy: 'circuit-name',
description: 'Time to generate the partial witness for a circuit',
events: ['circuit-simulation'],
},
{
name: 'circuit_proving_time_in_ms',
groupBy: 'circuit-name',
description: 'Time to prove circuit execution.',
events: ['circuit-proving'],
},
{
name: 'circuit_input_size_in_bytes',
groupBy: 'circuit-name',
Expand All @@ -128,6 +140,12 @@ export const Metrics = [
description: 'Size of the outputs (ie public inputs) from a circuit simulation.',
events: ['circuit-simulation'],
},
{
name: 'circuit_proof_size_in_bytes',
groupBy: 'circuit-name',
description: 'Size of the proof produced by a circuit.',
events: ['circuit-proving'],
},
{
name: 'tx_size_in_bytes',
groupBy: 'classes-registered',
Expand Down
60 changes: 47 additions & 13 deletions yarn-project/circuit-types/src/stats/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,40 @@ export type NodeSyncedChainHistoryStats = {
dbSize: number;
};

export type CircuitName =
| 'base-parity'
| 'root-parity'
| 'base-rollup'
| 'private-kernel-init'
| 'private-kernel-ordering'
| 'root-rollup'
| 'merge-rollup'
| 'private-kernel-inner'
| 'public-kernel-setup'
| 'public-kernel-app-logic'
| 'public-kernel-teardown'
| 'public-kernel-tail';

/** Stats for circuit simulation. */
export type CircuitSimulationStats = {
/** name of the event. */
eventName: 'circuit-simulation';
/** Name of the circuit. */
circuitName:
| 'base-parity'
| 'root-parity'
| 'base-rollup'
| 'private-kernel-init'
| 'private-kernel-ordering'
| 'root-rollup'
| 'merge-rollup'
| 'private-kernel-inner'
| 'public-kernel-setup'
| 'public-kernel-app-logic'
| 'public-kernel-teardown'
| 'public-kernel-tail';
circuitName: CircuitName;
/** Duration in ms. */
duration: number;
/** Size in bytes of circuit inputs. */
inputSize: number;
/** Size in bytes of circuit outputs (aka public inputs). */
outputSize: number;
};

/** Stats for witness generation. */
export type CircuitWitnessGenerationStats = {
/** name of the event. */
eventName: 'circuit-witness-generation';
/** Name of the circuit. */
circuitName: CircuitName;
/** Duration in ms. */
duration: number;
/** Size in bytes of circuit inputs. */
Expand All @@ -74,6 +90,22 @@ export type CircuitSimulationStats = {
outputSize: number;
};

/** Stats for proving a circuit */
export type CircuitProvingStats = {
/** Name of the event. */
eventName: 'circuit-proving';
/** Name of the circuit. */
circuitName: CircuitName;
/** Duration in ms. */
duration: number;
/** Size in bytes of circuit inputs. */
inputSize: number;
/** Size in bytes of circuit outputs (aka public inputs). */
outputSize: number;
/** Size in bytes of the proof. */
proofSize: number;
};

/** Stats for an L2 block built by a sequencer. */
export type L2BlockBuiltStats = {
/** Name of the event. */
Expand Down Expand Up @@ -206,6 +238,8 @@ export type Stats =
| L1PublishStats
| NodeSyncedChainHistoryStats
| CircuitSimulationStats
| CircuitProvingStats
| CircuitWitnessGenerationStats
| L2BlockBuiltStats
| L2BlockHandledStats
| NoteProcessorCaughtUpStats
Expand Down
94 changes: 8 additions & 86 deletions yarn-project/prover-client/src/orchestrator/orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
L2Block,
MerkleTreeId,
type ProcessedTx,
type PublicKernelRequest,
PublicKernelType,
type TxEffect,
toTxEffect,
Expand All @@ -15,7 +14,6 @@ import {
type ProvingTicket,
type PublicInputsAndProof,
} from '@aztec/circuit-types/interfaces';
import { type CircuitSimulationStats } from '@aztec/circuit-types/stats';
import {
type BaseOrMergeRollupPublicInputs,
BaseParityInputs,
Expand All @@ -41,7 +39,6 @@ import { createDebugLogger } from '@aztec/foundation/log';
import { promiseWithResolvers } from '@aztec/foundation/promise';
import { type Tuple } from '@aztec/foundation/serialize';
import { sleep } from '@aztec/foundation/sleep';
import { Timer } from '@aztec/foundation/timer';
import { type MerkleTreeOperations } from '@aztec/world-state';

import { inspect } from 'util';
Expand Down Expand Up @@ -311,7 +308,7 @@ export class ProvingOrchestrator {
private deferredProving<T>(
provingState: ProvingState | undefined,
request: (signal: AbortSignal) => Promise<T>,
callback: (result: T, durationMs: number) => void | Promise<void>,
callback: (result: T) => void | Promise<void>,
) {
if (!provingState?.verifyState()) {
logger.debug(`Not enqueuing job, state no longer valid`);
Expand All @@ -330,10 +327,7 @@ export class ProvingOrchestrator {
return;
}

const timer = new Timer();
const result = await request(controller.signal);
const duration = timer.ms();

if (!provingState?.verifyState()) {
logger.debug(`State no longer valid, discarding result`);
return;
Expand All @@ -345,7 +339,7 @@ export class ProvingOrchestrator {
return;
}

await callback(result, duration);
await callback(result);
} catch (err) {
if (err instanceof AbortedError) {
// operation was cancelled, probably because the block was cancelled
Expand All @@ -367,39 +361,6 @@ export class ProvingOrchestrator {
setImmediate(safeJob);
}

private emitCircuitSimulationStats(
circuitName: CircuitSimulationStats['circuitName'] | null,
inputSize: number,
outputSize: number,
duration: number,
) {
const stats: CircuitSimulationStats | undefined = circuitName
? {
eventName: 'circuit-simulation',
circuitName,
duration,
inputSize,
outputSize,
}
: undefined;
logger.debug(`Simulated ${circuitName} circuit duration=${duration}ms`, stats);
}

private getPublicKernelCircuitName(request: PublicKernelRequest) {
switch (request.type) {
case PublicKernelType.SETUP:
return 'public-kernel-setup';
case PublicKernelType.APP_LOGIC:
return 'public-kernel-app-logic';
case PublicKernelType.TEARDOWN:
return 'public-kernel-teardown';
case PublicKernelType.TAIL:
return 'public-kernel-tail';
default:
return null;
}
}

// Updates the merkle trees for a transaction. The first enqueued job for a transaction
private async prepareBaseRollupInputs(
provingState: ProvingState | undefined,
Expand Down Expand Up @@ -475,14 +436,7 @@ export class ProvingOrchestrator {
this.deferredProving(
provingState,
signal => this.prover.getBaseRollupProof(tx.baseRollupInputs, signal),
(result, duration) => {
this.emitCircuitSimulationStats(
'base-rollup',
tx.baseRollupInputs.toBuffer().length,
result.inputs.toBuffer().length,
duration,
);

result => {
validatePartialState(result.inputs.end, tx.treeSnapshots);
const currentLevel = provingState.numMergeLevels + 1n;
this.storeAndExecuteNextMergeLevel(provingState, currentLevel, index, [result.inputs, result.proof]);
Expand All @@ -506,13 +460,7 @@ export class ProvingOrchestrator {
this.deferredProving(
provingState,
signal => this.prover.getMergeRollupProof(inputs, signal),
(result, duration) => {
this.emitCircuitSimulationStats(
'merge-rollup',
inputs.toBuffer().length,
result.inputs.toBuffer().length,
duration,
);
result => {
this.storeAndExecuteNextMergeLevel(provingState, level, index, [result.inputs, result.proof]);
},
);
Expand Down Expand Up @@ -542,14 +490,7 @@ export class ProvingOrchestrator {
this.deferredProving(
provingState,
signal => this.prover.getRootRollupProof(inputs, signal),
(result, duration) => {
this.emitCircuitSimulationStats(
'root-rollup',
inputs.toBuffer().length,
result.inputs.toBuffer().length,
duration,
);

result => {
provingState.rootRollupPublicInputs = result.inputs;
provingState.finalProof = result.proof;

Expand All @@ -567,13 +508,7 @@ export class ProvingOrchestrator {
this.deferredProving(
provingState,
signal => this.prover.getBaseParityProof(inputs, signal),
(rootInput, duration) => {
this.emitCircuitSimulationStats(
'base-parity',
inputs.toBuffer().length,
rootInput.publicInputs.toBuffer().length,
duration,
);
rootInput => {
provingState.setRootParityInputs(rootInput, index);
if (provingState.areRootParityInputsReady()) {
const rootParityInputs = new RootParityInputs(
Expand All @@ -594,13 +529,7 @@ export class ProvingOrchestrator {
this.deferredProving(
provingState,
signal => this.prover.getRootParityProof(inputs, signal),
async (rootInput, duration) => {
this.emitCircuitSimulationStats(
'root-parity',
inputs.toBuffer().length,
rootInput.publicInputs.toBuffer().length,
duration,
);
async rootInput => {
provingState!.finalRootParityInput = rootInput;
await this.checkAndEnqueueRootRollup(provingState);
},
Expand Down Expand Up @@ -714,14 +643,7 @@ export class ProvingOrchestrator {
return this.prover.getPublicKernelProof(request, signal);
}
},
(result, duration) => {
this.emitCircuitSimulationStats(
this.getPublicKernelCircuitName(request),
request.inputs.toBuffer().length,
0,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is why the benchmark comment says the public circuit's output increased massively, it was 0 before 👀

circuit_output_size_in_bytes (public-kernel-app-logic): 52,231 (+99%)
circuit_output_size_in_bytes (public-kernel-tail): 7,659 (+96%)
circuit_output_size_in_bytes (public-kernel-teardown): 52,231 (+50%)
circuit_output_size_in_bytes (public-kernel-setup): 52,231 (+50%)

duration,
);

result => {
const nextKernelRequest = txProvingState.getNextPublicKernelFromKernelProof(functionIndex, result.proof);
// What's the status of the next kernel?
if (nextKernelRequest.code === TX_PROVING_CODE.NOT_READY) {
Expand Down
38 changes: 38 additions & 0 deletions yarn-project/prover-client/src/prover/bb_prover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
import { randomBytes } from '@aztec/foundation/crypto';
import { createDebugLogger } from '@aztec/foundation/log';
import { type Tuple } from '@aztec/foundation/serialize';
import { Timer } from '@aztec/foundation/timer';
import {
ServerCircuitArtifacts,
type ServerProtocolArtifact,
Expand Down Expand Up @@ -62,6 +63,7 @@ import {
generateProof,
verifyProof,
} from '../bb/execute.js';
import { circuitTypeToCircuitName, emitCircuitProvingStats, emitCircuitWitnessGenerationStats } from '../stats.js';
import { type CircuitProver, KernelArtifactMapping } from './interface.js';

const logger = createDebugLogger('aztec:bb-prover');
Expand Down Expand Up @@ -268,7 +270,15 @@ export class BBNativeRollupProver implements CircuitProver {

logger.debug(`Generating witness data for ${circuitType}`);

const timer = new Timer();
const outputWitness = await simulator.simulateCircuit(witnessMap, artifact);
emitCircuitWitnessGenerationStats(
circuitTypeToCircuitName(circuitType),
timer.ms(),
witnessMap.size * Fr.SIZE_IN_BYTES,
outputWitness.size * Fr.SIZE_IN_BYTES,
logger,
);

// Now prove the circuit from the generated witness
logger.debug(`Proving ${circuitType}...`);
Expand All @@ -293,6 +303,16 @@ export class BBNativeRollupProver implements CircuitProver {
// Read the proof and then cleanup up our temporary directory
const proof = await fs.readFile(`${provingResult.proofPath!}/${PROOF_FILENAME}`);

// does not include reading the proof from disk above because duration comes from the bb wrapper
emitCircuitProvingStats(
circuitTypeToCircuitName(circuitType),
provingResult.duration,
witnessMap.size * Fr.SIZE_IN_BYTES,
outputWitness.size * Fr.SIZE_IN_BYTES,
proof.length,
logger,
);

await fs.rm(bbWorkingDirectory, { recursive: true, force: true });

logger.info(`Generated proof for ${circuitType} in ${provingResult.duration} ms, size: ${proof.length} fields`);
Expand Down Expand Up @@ -334,8 +354,17 @@ export class BBNativeRollupProver implements CircuitProver {

logger.debug(`Generating witness data for ${circuitType}`);

const timer = new Timer();
const outputWitness = await simulator.simulateCircuit(witnessMap, artifact);

emitCircuitWitnessGenerationStats(
circuitTypeToCircuitName(circuitType),
timer.ms(),
witnessMap.size * Fr.SIZE_IN_BYTES,
outputWitness.size * Fr.SIZE_IN_BYTES,
logger,
);

const outputType = convertOutput(outputWitness);

// Now prove the circuit from the generated witness
Expand Down Expand Up @@ -365,6 +394,15 @@ export class BBNativeRollupProver implements CircuitProver {
`Generated proof for ${circuitType} in ${provingResult.duration} ms, size: ${proof.proof.length} fields`,
);

emitCircuitProvingStats(
circuitTypeToCircuitName(circuitType),
provingResult.duration,
witnessMap.size * Fr.SIZE_IN_BYTES,
outputWitness.size * Fr.SIZE_IN_BYTES,
proof.binaryProof.buffer.length,
logger,
);

return [outputType, proof];
} finally {
await fs.rm(bbWorkingDirectory, { recursive: true, force: true });
Expand Down
Loading
Loading