Merge rust-bitcoin/rust-bitcoin#4485: Add `Builder::with_capacity()`

d003d48592 Add `Builder::with_capacity()` (Daniel Roberts)
e492f94289 Update `ScriptBuf::with_capacity` docs (Daniel Roberts)

Pull request description:

  Enable the creation of `bitcoin::script::Builder` with a preallocated capacity.

  This is pretty minor, but it provides a small speedup if used correctly. I've observed a 0.4% speedup and a 0.7% speedup in two code bases that create lots of outputs (on the order of tens to hundreds of thousands). It provided a much larger speedup (5% or so) in the latter code base before some other optimizations dwarfed it.

  I have a branch that also uses it for `ScriptBufExt::new_*()` but while it provides a small performance improvement for all script types except one, `ScriptBufExt::new_p2tr()` actually causes a small performance regression. Since the only use case I have for creating lots and lots of scripts is in taproot with CHECKTEMPLATEVERIFY, I'm holding back that change if/until I figure out what's going on exactly (and hopefully resolve it).

ACKs for top commit:
  tcharding:
    ACK d003d48592
  apoelstra:
    ACK d003d4859251abb01929ccab6009a02e0c96b0cd; successfully ran local tests

Tree-SHA512: 51137574ca3d9dc5c319df124f470abd0f82413c093a5636af0439eb0fc2ad01dcf83df366a02279fc7d28feed24aa8c7db33b3c474d8bde7a9b6636343f8e9a
This commit is contained in:
merge-script 2025-05-13 17:16:54 +00:00
commit bc93498b3e
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
3 changed files with 12 additions and 1 deletions

View File

@ -21,6 +21,10 @@ impl Builder {
#[inline] #[inline]
pub const fn new() -> Self { Builder(ScriptBuf::new(), None) } pub const fn new() -> Self { Builder(ScriptBuf::new(), None) }
/// Constructs a new empty script builder with at least the specified capacity.
#[inline]
pub fn with_capacity(capacity: usize) -> Self { Builder(ScriptBuf::with_capacity(capacity), None) }
/// Returns the length in bytes of the script. /// Returns the length in bytes of the script.
pub fn len(&self) -> usize { self.0.len() } pub fn len(&self) -> usize { self.0.len() }

View File

@ -218,6 +218,13 @@ fn script_builder() {
); );
} }
#[test]
fn script_builder_with_capacity() {
let script = Builder::with_capacity(42);
assert!(script.into_script().capacity() >= 42);
}
#[test] #[test]
fn script_generators() { fn script_generators() {
let pubkey = "0234e6a79c5359c613762d537e0e19d86c77c1666d8c9ab050f23acd198e97f93e" let pubkey = "0234e6a79c5359c613762d537e0e19d86c77c1666d8c9ab050f23acd198e97f93e"

View File

@ -71,7 +71,7 @@ impl ScriptBuf {
Script::from_boxed_bytes(self.into_bytes().into_boxed_slice()) Script::from_boxed_bytes(self.into_bytes().into_boxed_slice())
} }
/// Constructs a new empty script with pre-allocated capacity. /// Constructs a new empty script with at least the specified capacity.
#[inline] #[inline]
pub fn with_capacity(capacity: usize) -> Self { pub fn with_capacity(capacity: usize) -> Self {
ScriptBuf::from_bytes(Vec::with_capacity(capacity)) ScriptBuf::from_bytes(Vec::with_capacity(capacity))