Space efficient custom_panic
(take 2)
#3952
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
Our implementation of
custom_panic
can consume up to 25kb in contracts. This happens because it relies on theformat!
macro and, consequently, onstd::fmt::write
. They include many more functions in the contract and utilize dynamic dispatch, a technique that hinders compiler and link side optimizations for size reduction.Summary of Changes
I implemented a new
custom_panic
that functions independently with only primitive (and unsafe) operations. It needs the stabilization offmt::Arguments::as_str
, which is happening in Rust 1.84 (see rust-lang/rust#132511).Size comparison
Take this simple contract as an example:
The binary size has whooping 17696 bytes (17kb).
The contract with an empty
custom_panic
function has 10336 bytes (10kb), so panic is consuming 7360 bytes.The contract with my new implementation has 11504 bytes (11kb), so my implementation has 1168 bytes.
New error messages
The members of
fmt::Arguments
are all private, so I cannot build custom panic messages during runtime as Rust does (think about the error you get when you access an invalid index from a vector: we can only know the index and the vector length during execution time). These messages will be elided in the new panic implementation (see examples below). Error messages whose content is known at compile time will still be shown normally.The formatting is also different. It is more efficient to call
sol_log
multiple times than to format a string.Accessing an invalid index from a vector:
OLD:
NEW:
Calling unwrap on a None:
OLD:
NEW:
Alternative implementation
For a better log experience (in my opinion), I prefer the implementation in #3951. It is larger, but the messages are more organized.