Skip to content

perf: set release opt-level = 2 (instead of s) - #1278

Merged
bitwalker merged 2 commits into
nextfrom
opt-level-2
Jul 17, 2026
Merged

perf: set release opt-level = 2 (instead of s)#1278
bitwalker merged 2 commits into
nextfrom
opt-level-2

Conversation

@greenhat

@greenhat greenhat commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Size-optimized LLVM output leaves execution improvements on the table for release guest builds, while the resulting package-size tradeoff depends on the guest.

On the batch-kernel #1242, isolated opt-s versus opt-2 measurements showed:

Workload Cycle reduction
Batch scenario 1 13.6% (34,916 → 30,151)
Batch note-erasure scenario 13.5% (30,553 → 26,436)
Tampered-preimage rejection 11.2% (950 → 844)
Consume-before-create rejection 9.8% (15,969 → 14,411)

The stripped batch-kernel MAST also decreased by 9.9%, from 112,218 to 101,144 bytes. On this branch, the updated integration-network pins likewise show cycle reductions across the counter, P2ID, custom transaction script, and P2IDE workflows.

This is primarily an execution-speed optimization: package-size effects depend on the guest. The four small example packages measured on this branch grow by 6.9–13.7% under opt-2.

@greenhat
greenhat requested a review from bitwalker July 14, 2026 11:56
@greenhat
greenhat marked this pull request as ready for review July 14, 2026 11:56
let tx_script_package = tx_script_test.compile_package();
assert!(tx_script_package.is_library(), "expected library");
expect!["14238"].assert_eq(stripped_mast_size_str(&tx_script_package));
expect!["16188"].assert_eq(stripped_mast_size_str(&tx_script_package));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It looks like these larger programs actually grow considerably larger, while the smaller programs get smaller, but not to the same degree - are we sure that this is on-balance a better default choice? Saving ~500 cycles on a program < 10k cycles is probably not worth losing ~2k+ cycles on programs > 10k cycles - the more expensive the program is to execute, the more important the savings become - but it seems here that only the smaller programs see the benefit (though that may simply be due to the sample set here).

I'd suggest we try to support deriving the optimzation level from the OptLevel setting in Options - and choose a default OptLevel that maps cleanest to what we want the Cargo default to be.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It looks like these larger programs actually grow considerably larger, while the smaller programs get smaller, but not to the same degree - are we sure that this is on-balance a better default choice? Saving ~500 cycles on a program < 10k cycles is probably not worth losing ~2k+ cycles on programs > 10k cycles - the more expensive the program is to execute, the more important the savings become - but it seems here that only the smaller programs see the benefit (though that may simply be due to the sample set here).

Size

For the programs that we're tracking, their size increased by 7-13%. I'd call them small (12-19 KB). The batch kernel size, on the other hand, decreased by 9.9%, from 112,218 to 101,144 bytes, as I noted in the PR description. So, small programs increase in size, but large programs decrease. My take is that at some point in the program size spectrum, the increase flips to a decrease, but we don't have enough data points to confirm.

Speed

All the programs demonstrate cycle count reduction under opt-level=2. For the small programs, it's a 3-7% reduction. For the batch kernel (see the PR description), it's a 13% reduction for the happy path scenario.

Overall, I think it's a good tradeoff to pay a 7-13% size increase for small programs and get a speed increase for all programs and size reduction for large programs. It's worth adopting it as our opt-level override.

I'd suggest we try to support deriving the optimization level from the OptLevel setting in Options - and choose a default OptLevel that maps cleanest to what we want the Cargo default to be.

IIUC, the only way for the user to set it is via the --optimize option. Should we consider also having it in the miden-project.toml? What should we do if the user sets opt-level in their Cargo.toml? Hard error? Currently, we're overriding the opt-level option set elsewhere. We're not setting the Cargo default.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Yes, that's correct --optimize=LEVEL has to be passed to change it, which is fine.

We can add this as a supported profile option in miden-project.toml. If someone also sets it in their Cargo.toml it'll just get ignored (since our override will take precedence). I don't think we need to try and handle it being set there for the time being - if it ends up being an annoyance, we can always pull that metadata from Cargo.toml and check if it conflicts, or just document that it has to be set via one of the two methods mentioned above.

For now though, I think just having the compiler wired up to look at the session opt_level for this purpose is sufficient - we can make it more prominent/easy to set in the future if desired.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 1a605ca

greenhat added 2 commits July 16, 2026 09:05
Size-optimized LLVM output leaves execution improvements on the table for release guest builds, while the resulting package-size tradeoff depends on the guest.

Select optimization level two while preserving the existing release LTO, codegen-unit, and panic settings. Update the recorded execution-cycle and stripped MAST size measurements to reflect the new release output.
Release Cargo guest builds hard-coded LLVM level two, so explicit compiler optimization choices could not tune the Rust guest compilation profile.

Map compiler optimization levels to Cargo profile values and build guests with the selected value. Preserve level two for the existing default and balanced modes while allowing basic, maximum, and size-focused modes to drive Cargo.
@bitwalker
bitwalker merged commit 6def83a into next Jul 17, 2026
17 checks passed
@bitwalker
bitwalker deleted the opt-level-2 branch July 17, 2026 01:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants