Skip to content

Commit 042c02e

Browse files
authored
fix: Improve performance of witness read in ACVM native (#18157)
We were doing a lot of buffer reallocations. Pushing the buffers to an array and concatenating at the end with given length improves performance of witgen in some circuits by ~4x.
2 parents 4ca4965 + b10457b commit 042c02e

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

yarn-project/simulator/src/private/acvm_native.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,21 +103,26 @@ export async function executeNativeCircuit(
103103
logger.debug(`Calling ACVM with ${args.join(' ')}`);
104104

105105
const processPromise = new Promise<string>((resolve, reject) => {
106-
let outputWitness = Buffer.alloc(0);
107-
let errorBuffer = Buffer.alloc(0);
106+
const outChunks: Buffer[] = [];
107+
const errChunks: Buffer[] = [];
108+
let outLen = 0;
109+
let errLen = 0;
108110
const acvm = proc.spawn(pathToAcvm, args);
109-
acvm.stdout.on('data', data => {
110-
outputWitness = Buffer.concat([outputWitness, data]);
111+
acvm.stdout.on('data', (data: Buffer) => {
112+
outChunks.push(data);
113+
outLen += data.length;
111114
});
112-
acvm.stderr.on('data', data => {
113-
errorBuffer = Buffer.concat([errorBuffer, data]);
115+
acvm.stderr.on('data', (data: Buffer) => {
116+
errChunks.push(data);
117+
errLen += data.length;
114118
});
115119
acvm.on('close', code => {
116120
if (code === 0) {
117-
resolve(outputWitness.toString('utf-8'));
121+
resolve(Buffer.concat(outChunks, outLen).toString('utf-8'));
118122
} else {
119-
logger.error(`From ACVM: ${errorBuffer.toString('utf-8')}`);
120-
reject(errorBuffer.toString('utf-8'));
123+
const stderr = Buffer.concat(errChunks, errLen);
124+
logger.error(`From ACVM: ${stderr.toString('utf-8')}`);
125+
reject(stderr.toString('utf-8'));
121126
}
122127
});
123128
});
@@ -129,6 +134,9 @@ export async function executeNativeCircuit(
129134
const outputWitnessFileName = `${workingDirectory}/output-witness.gz`;
130135
await fs.copyFile(outputWitnessFileName, outputFilename);
131136
}
137+
// TODO: We shouldn't be parsing the witness from stdout, it's not very performant, and we end up with two ways of fetching the witness.
138+
// We probably should implement the WitnessStack type, run the ACVM with msgpack serialization mode (env variable), and ungzip and parse the witness from
139+
// the outputted gz witness file.
132140
const witness = parseIntoWitnessMap(output);
133141
return { status: ACVM_RESULT.SUCCESS, witness, duration };
134142
} catch (error) {

0 commit comments

Comments
 (0)