0xMiden / 0xMiden/web-sdk

prove({ prover: newLocalProver() }) is 18-49x slower than prove() with no argument

Aperta
#350 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
TypeScript
Stelle
1
Fork
21
Merge medio
12h 14m
PR unite (30g)
41

Descrizione

Passing a prover to `prove()` is around fifty times slower than leaving the argument off, for the same transaction.

I hit this while timing proving for an app, and the gap was large enough that I assumed my measurement was wrong. It reproduces on the same request object, in the same page, back to back.

### Repro

```js
const script = await client.compile.txScript({
code: "use miden::core::sys\nbegin\n push.1 drop\n exec.sys::truncate_stack\nend\n",
});
const request = new TransactionRequestBuilder().withCustomScript(script).build();

// A — no prover argument
let staged = await client.transactions.executeRequest(account, request);
await staged.prove();

// B — explicit local prover
const prover = TransactionProver.newLocalProver();
staged = await client.transactions.executeRequest(account, request);
await staged.prove({ prover });
```

Timings on macOS, 8 cores, Chrome 152, `@miden-sdk/miden-sdk@0.15.9` single threaded, testnet:

```
A prove() 1925 ms 1267 ms
B prove({ prover }) 209043 ms 62244 ms
```

A second run on the same setup gave 2940 / 2726 ms for A and 53242 / 49823 ms for B. The later B call is faster than the first in both runs, so this is not degradation over time. The ratio lands between 18x and 49x depending on the run.

Both paths are local. I checked that by pulling the network down after the client was ready and the transaction executed, then calling `prove()` with no argument: it completed offline in 1742 ms. So the fast path is not delegating to a remote prover.

### Where the paths diverge

`proveResult` in the SDK sends the two cases to different calls, and `defaultProver` is null unless the app sets one:

```js
const prover = opts?.prover ?? defaultProver;
return prover
? await inner.proveTransaction(result, prover)
: await inner.proveTransaction(result);
```

The two branches resolve different provers: `custom_prover.get_prover()` versus `client.prover()`. `newLocalProver()` builds `LocalTransactionProver::new(ProvingOptions::default())`. I could not work out from here what `client.prover()` resolves to, so I am reporting the measurement rather than guessing at the cause.

This may be the same routing asymmetry described in #312, though that one is about `batch()` and the main thread, and here both calls go through the worker wrapper.

### Why it matters

`newLocalProver()` reads as the ordinary way to prove locally, and an app that wants local proving will reach for it. Nothing in the README or the API surface suggests the argument changes performance by this much. A note in the docs would help even if the behaviour is intended.

Environment: macOS, Chrome 152, node 24, pnpm 10.18, SDK 0.15.9, testnet.

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Look at the `proveResult` function in the SDK to see the two branches: one with a prover argument and one without. Examine `client.prover()` and `LocalTransactionProver::new(ProvingOptions::default())` to understand the performance difference. Run the provided repro script to confirm timings, then profile both paths to identify bottlenecks. The fix likely involves aligning the prover configurations or optimizing the custom prover path.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
javascript, nodejs, typescript
Ambito
backend, performance
Tipo di issue
Bug
Difficoltà
3/5
Tempo stimato
1-2 giorni
Stato di attività
Attiva
Chiarezza
Specificata chiaramente
Idoneità per principianti
65/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.