Fast write constraints
Jordi Baylina jordi@baylina.cat
Sat, 25 Jul 2020 13:55:17 +0200
4 files changed,
83 insertions(+),
37 deletions(-)
M
package-lock.json
→
package-lock.json
@@ -576,9 +576,9 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true }, "fastfile": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.8.tgz", - "integrity": "sha512-i78nuMJUoNZP5J1bPjecK07+ifHMJTBnJND/4QMUYp++DDltoAjQcIeFIWoUalt7n324fvvzWR55+WEPQUA7tQ==" + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.9.tgz", + "integrity": "sha512-njh6lH2SJiS0u0JofJQf2YfEOSgGfbYPtmFnpEXXy6OilWoX1wGw3klaSKIwhq8+E5MqYpqJXMiaqmptaU2wig==" }, "ffiasm": { "version": "0.0.2",
M
package.json
→
package.json
@@ -31,7 +31,7 @@ },
"dependencies": { "chai": "^4.2.0", "circom_runtime": "0.0.6", - "fastfile": "0.0.8", + "fastfile": "0.0.9", "ffiasm": "0.0.2", "ffjavascript": "0.2.4", "ffwasm": "0.0.7",
M
src/compiler.js
→
src/compiler.js
@@ -28,8 +28,30 @@ const utils = require("./utils");
const buildR1cs = require("./r1csfile").buildR1cs; const BigArray = require("./bigarray"); const buildSyms = require("./buildsyms"); +const {performance} = require("perf_hooks"); module.exports = compile; +const measures = {}; + +function ms2String(v) { + v = Math.floor(v); + const ms = v % 1000; + v = Math.floor(v/1000); + const secs = v % 60; + v = Math.floor(v/60); + const mins = v % 60; + v = Math.floor(v/60); + const hours = v % 24; + const days = Math.floor(v/24); + let S = ""; + if (days) S = S + days + "D "; + if ((S!="")||(hours)) S = S + hours.toString().padStart(2, "0") + ":"; + if ((S!="")||(mins)) S = S + mins.toString().padStart(2, "0") + ":"; + if ((S!="")||(secs)) S = S + secs.toString().padStart(2, "0"); + S+="."; + S = S + ms.toString().padStart(3, "0"); + return S; +} async function compile(srcFile, options) { options.prime = options.prime || Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");@@ -44,9 +66,9 @@ ctx.verbose= options.verbose || false;
ctx.mainComponent = options.mainComponent || "main"; ctx.newThreadTemplates = options.newThreadTemplates; - if (ctx.verbose) console.time("Construction Phase"); + measures.constructionPhase = -performance.now(); constructionPhase(ctx, srcFile); - if (ctx.verbose) console.timeEnd("Construction Phase"); + measures.constructionPhase += performance.now(); if (ctx.verbose) console.log("NConstraints Before: "+ctx.constraints.length); if (ctx.verbose) console.log("NSignals Before: "+ctx.signals.length);@@ -60,14 +82,14 @@ throw new Error("A main component must be defined");
} if (ctx.verbose) console.log("Classify Signals"); - if (ctx.verbose) console.time("Classify Signals"); + measures.classifySignals = -performance.now(); classifySignals(ctx); - if (ctx.verbose) console.timeEnd("Classify Signals"); + measures.classifySignals += performance.now(); if (ctx.verbose) console.log("Reduce Constants"); - if (ctx.verbose) console.time("Reduce Constants"); + measures.reduceConstants = -performance.now(); reduceConstants(ctx); - if (ctx.verbose) console.timeEnd("Reduce Constants"); + measures.reduceConstants += performance.now(); if (options.reduceConstraints) {@@ -81,17 +103,17 @@ oldNConstrains = ctx.constraints.length;
reduceConstrains(ctx); } */ - if (ctx.verbose) console.time("Reduce Constraints"); + measures.reduceConstraints = -performance.now(); await reduceConstrains(ctx); - if (ctx.verbose) console.timeEnd("Reduce Constraints"); + measures.reduceConstraints += performance.now(); } if (ctx.verbose) console.log("NConstraints After: "+ctx.constraints.length); - if (ctx.verbose) console.time("Generate Witness Names"); + measures.generateWitnessNames = -performance.now(); generateWitnessNames(ctx); - if (ctx.verbose) console.timeEnd("Generate Witness Names"); + measures.generateWitnessNames += performance.now(); if (ctx.error) { throw(ctx.error);@@ -99,19 +121,19 @@ }
if (options.cSourceWriteStream) { if (ctx.verbose) console.log("Generating c..."); - if (ctx.verbose) console.time("Generate C"); + measures.generateC = -performance.now(); ctx.builder = new BuilderC(options.prime); build(ctx); const rdStream = ctx.builder.build(); rdStream.pipe(options.cSourceWriteStream); - if (ctx.verbose) console.timeEnd("Generate C"); + measures.generateC += performance.now(); // await new Promise(fulfill => options.cSourceWriteStream.on("finish", fulfill)); } if ((options.wasmWriteStream)||(options.watWriteStream)) { if (ctx.verbose) console.log("Generating wasm..."); - if (ctx.verbose) console.time("Generating wasm"); + measures.generateWasm = -performance.now(); ctx.builder = new BuilderWasm(options.prime); build(ctx); if (options.wasmWriteStream) {@@ -122,7 +144,7 @@ if (options.watWriteStream) {
const rdStream = ctx.builder.build("wat"); rdStream.pipe(options.watWriteStream); } - if (ctx.verbose) console.timeEnd("Generate wasm"); + measures.generateWasm += performance.now(); // await new Promise(fulfill => options.wasmWriteStream.on("finish", fulfill)); }@@ -131,24 +153,27 @@ // const mainCode = gen(ctx,ast);
if (ctx.error) throw(ctx.error); if (options.r1csFileName) { - if (ctx.verbose) console.log("Generating r1cs..."); - if (ctx.verbose) console.time("Generating r1cs"); + measures.generateR1cs = -performance.now(); await buildR1cs(ctx, options.r1csFileName); - if (ctx.verbose) console.timeEnd("Generating r1cs"); + measures.generateR1cs += performance.now(); } if (options.symWriteStream) { - if (ctx.verbose) console.log("Generating syms..."); - if (ctx.verbose) console.time("Generating syms"); + measures.generateSyms = -performance.now(); const rdStream = buildSyms(ctx); rdStream.pipe(options.symWriteStream); - if (ctx.verbose) console.timeEnd("Generating syms"); + measures.generateSyms += performance.now(); - // await new Promise(fulfill => options.symWriteStream.on("finish", fulfill)); + await new Promise(fulfill => options.symWriteStream.on("finish", fulfill)); } // const def = buildCircuitDef(ctx, mainCode); + if (ctx.verbose) { + for (let [mStr, mValue] of Object.entries(measures)) { + console.log(mStr + ": " + ms2String(mValue)); + } + } }
M
src/r1csfile.js
→
src/r1csfile.js
@@ -94,23 +94,44 @@ await fd.writeULE32(mapSize, pMapSize);
await fd.close(); - async function writeConstraint(c) { - await writeLC(c.a); - await writeLC(c.b); - await writeLC(ctx.lc.neg(c.c)); - } + function writeConstraint(c) { + const n8 = ctx.F.n8; + const idxA = Object.keys(c.a.coefs); + const idxB = Object.keys(c.b.coefs); + const idxC = Object.keys(c.c.coefs); + const buff = new Uint8Array((idxA.length+idxB.length+idxC.length)*(n8+4) + 12); + const buffV = new DataView(buff.buffer); + let o=0; - async function writeLC(lc) { - const idxs = Object.keys(lc.coefs); - await fd.writeULE32(idxs.length); - for (let s in lc.coefs) { - let lSignal = ctx.signals[s]; + buffV.setUint32(o, idxA.length, true); o+=4; + for (let i=0; i<idxA.length; i++) { + const coef = idxA[i]; + let lSignal = ctx.signals[coef]; + while (lSignal.e >=0 ) lSignal = ctx.signals[lSignal.e]; + buffV.setUint32(o, lSignal.id, true); o+=4; + ctx.F.toRprLE(buff, o, c.a.coefs[coef]); o+=n8; + } + buffV.setUint32(o, idxB.length, true); o+=4; + for (let i=0; i<idxB.length; i++) { + const coef = idxB[i]; + let lSignal = ctx.signals[coef]; while (lSignal.e >=0 ) lSignal = ctx.signals[lSignal.e]; + buffV.setUint32(o, lSignal.id, true); o+=4; - await fd.writeULE32(lSignal.id); - await writeBigInt(lc.coefs[s]); + ctx.F.toRprLE(buff, o, c.b.coefs[coef]); o+=n8; } + + buffV.setUint32(o, idxC.length, true); o+=4; + for (let i=0; i<idxC.length; i++) { + const coef = idxC[i]; + let lSignal = ctx.signals[coef]; + while (lSignal.e >=0 ) lSignal = ctx.signals[lSignal.e]; + buffV.setUint32(o, lSignal.id, true); o+=4; + ctx.F.toRprLE(buff, o, ctx.F.neg(c.c.coefs[coef])); o+=n8; + } + + return fd.write(buff); } async function writeBigInt(n, pos) {