-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce Binary sizes #585
Comments
psbt
, interpreter
, descriptor
and policy
. This would reduce the compilation time and memory usage by offering flexibility.
Using a third party tool
|
Removing monomorphization for the script context would be very welcome, I hope you can work on it soon. Any thoughts about removing the Ctx type param in favor of dynamic dispatch, or maybe even passing the context as a simple enum argument? |
Let's see how much mileage we could get out of reducing monomorphization by moving it to the edges. Dynamic dispatch on every single descriptor-related function would be a pretty heavy price to pay I think. I'm also not totally sure, technically, if we could do it. If all our uses of |
https://jmmv.dev/2023/08/rust-static-dispatch-failed-experiment.html is maybe relevant to this discussion. |
@sanket1729 do you plan to pick this up? It would be very helpful now that minitapscript was merged to Bitcoin Core. I already use the Segwitv0 context and want to also use the Taproot context, but it adds too much binary code while I would expect the difference to be quite minimal. |
@benma, I will take a stab at this today. |
@sanket1729 how did it go? 😄 |
@benma, not good. This was more invasive than I anticipated. I am still working on it. @apoelstra, this is what I am attempting at a high level.
#[derive(Clone)]
pub struct MsUnChecked<Pk: MiniscriptKey> {
/// A node in the AST.
pub node: Terminal<Pk>,
/// The correctness and malleability type information for the AST node.
pub ty: types::Type,
/// Additional information helpful for extra analysis.
pub ext: types::extra_props::ExtData,
}
#[derive(Clone)]
pub struct Miniscript<Pk: MiniscriptKey, Ctx: ScriptContext> {
/// A node in the AST.
pub inner: MsUnChecked<Pk>,
/// Context PhantomData. Only accessible inside this crate
phantom: PhantomData<Ctx>,
}
/// APIs that stay the same. Inside the same impl block Miniscript<Pk, Ctx>
impl Miniscript<Pk, Ctx> {
fn encode(&self) -> Script {
self.inner.encode()
}
}
/// Special purpose APIs that are different for each context.
impl Miniscript<Pk, SegwitV0> {
fn script_size(&self) -> usize {
self.inner.script_size(Ctx::Segwitv0) // script_size would be function in MsUnchchecked that takes paramter instead of generic parametrization .
}
} @apoelstra, any comments on this approach? |
@sanket1729 that sounds great! The hardest part (aside from this probably touching every single LOC in the library :)) sounds like the conversions. But maybe if our public API consists only of wrapper types, and all the recursive types stay as Also cc #484 ... I think we're blocked on Rust language stuff to be able to move to a flat representation but wanted to remind people of that issue nonetheless. Since we're thinking about changing data representations. |
c8d3b9a fix formatting in big example (Riccardo Casatta) bc47538 add taproot calls in big executable (Riccardo Casatta) 545bbbe add satisfy call in big executable (Riccardo Casatta) 959546b add psbt finalize call in big executable (Riccardo Casatta) 883132e add policy calls in big executable (Riccardo Casatta) ec751fb Introduce an example binary useful for profiling (Riccardo Casatta) Pull request description: Tools like `cargo bloat` don't work on libraries but on final executable. As seen in #585 and #584 the parse example is used as a base to profile binary bloat. However, since the parse example is not using all the API surface, we may have good optimization that are not recognized as such because the optimized function are not in the tree of the functions used. For benchmarking size optimization a specific binary that ideally touch all the API surface is needed and this MR introduce it. More coverage will be added if this seem a good idea for reviewers. ACKs for top commit: apoelstra: ACK c8d3b9a thanks! Tree-SHA512: 70ac51a222b59b5de76a2ef314be2f3d82b3f5831d90dd7110929a4956a27a6d1eaa4889525dbf54575fb7e07db60f19d67556f2539b61979b4ba681fec0523e
Thanks for your hard work, just adding my experience here: I recently updated BDK in my project and the update also bumped rust-miniscript from v9.0.2 to v10.0.0. Between these two versions the code size for miniscript went from 72.0KiB to 129.7KiB! Maybe before doing more "invasive" work just looking at the diff between these two versions could bring pretty big improvements.. |
@sanket1729 is there a way forward here? Would appreciate it. I am still kind of blocked from using additional contexts due to the binary bloat it incurs. |
There are a lot of things we can do in the longer term to help this. We can split out the crates into multiple separate crates like
psbt
,interpreter
,descriptor
andpolicy
. This would reduce the compilation time and memory usage by offering flexibility.As pointed by benma , this is because we use a lot of generics. In particular, almost every single function is being monomorphized for each
Ctx
.There are 4 types of Contexts (Bare, Legacyp2sh, Segwitv0, Taproot) that are compiled for each descriptor method. One idea might be to define
Terminal
without the Context. GuardMiniscript
with appropriate Context while in the constructorMiniscript::from_ast
. This should significantly reduce the code duplication and have a good impact on binary sizes.Originally posted by @sanket1729 in #584 (comment)
The text was updated successfully, but these errors were encountered: