Skip to content

Commit 360af7e

Browse files
committed
Merge #97: Add benchmarks
34e6ab9 CI: Run benchmarks (Tobin C. Harding) 8f2bac7 Add benchmarks (Tobin C. Harding) Pull request description: Add benchmarks for parsing and encoding bitcoin addresses. Also add two unit tests that parse the same address string used in the benchmarks. Specifically benchmark: - decoding an address - encoding an address with allocation - encoding an address without allocation Do so for both Bitcoin bech32 addresses and Bitcoin bech32m addresses. Patch 1 is preparatory clean up to the readme. ACKs for top commit: apoelstra: ACK 34e6ab9 Tree-SHA512: 10d4bdf108fec39e94f9a493fe680842b2f47d3fee0139b301e927dbc9273441d940194ee36cb71d2813b21fa343f8fc2d60ee45f43c276beb9dc8e41c9ceb7d
2 parents 8f6d5d9 + 34e6ab9 commit 360af7e

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

.github/workflows/rust.yml

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ jobs:
4848
env:
4949
DO_DOCSRS: true
5050
DO_FMT: true
51+
DO_BENCH: true
5152
run: ./contrib/test.sh
5253

5354
MSRV:

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,9 @@ git config --local core.hooksPath githooks/
2727
```
2828

2929
Alternatively add symlinks in your `.git/hooks` directory to any of the githooks we provide.
30+
31+
32+
## Benchmarks
33+
34+
We use a custom Rust compiler configuration conditional to guard the benchmark code. To run the
35+
benchmarks use: `RUSTFLAGS='--cfg=bench' cargo +nightly bench`.

contrib/test.sh

+12
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,16 @@ if [ "${DO_DOCS-false}" = true ]; then
7171
RUSTDOCFLAGS="-D warnings" cargo +stable doc --all-features
7272
fi
7373

74+
# Bench if told to.
75+
if [ "${DO_BENCH-false}" = true ]
76+
then
77+
# Technically we could use beta too but we only run this in CI using nightly.
78+
if [ "$NIGHTLY" = false ]; then
79+
echo "DO_BENCH requires a nightly toolchain (consider using RUSTUP_TOOLCHAIN)"
80+
exit 1
81+
fi
82+
83+
RUSTFLAGS='--cfg=bench' cargo bench
84+
fi
85+
7486
exit 0

src/lib.rs

+99
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,14 @@ assert_eq!(variant, Variant::Bech32);
3131
3232
#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
3333
// Experimental features we need.
34+
#![cfg_attr(bench, feature(test))]
3435
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3536
// Coding conventions
3637
#![deny(missing_docs)]
3738

39+
#[cfg(bench)]
40+
extern crate test;
41+
3842
#[cfg(feature = "alloc")]
3943
extern crate alloc;
4044

@@ -1399,4 +1403,99 @@ mod tests {
13991403
assert_eq!(&res, [0x00, 0x01, 0x02].as_ref());
14001404
assert_eq!(variant, Variant::Bech32);
14011405
}
1406+
1407+
#[test]
1408+
#[cfg(feature = "alloc")]
1409+
fn decode_bitcoin_bech32_address() {
1410+
let addr = "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq";
1411+
let (hrp, _data, variant) = crate::decode(addr).expect("address is well formed");
1412+
assert_eq!(hrp, "bc");
1413+
assert_eq!(variant, Variant::Bech32)
1414+
}
1415+
1416+
#[test]
1417+
#[cfg(feature = "alloc")]
1418+
fn decode_bitcoin_bech32m_address() {
1419+
let addr = "bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg3297";
1420+
let (hrp, _data, variant) = crate::decode(addr).expect("address is well formed");
1421+
assert_eq!(hrp, "bc");
1422+
assert_eq!(variant, Variant::Bech32m)
1423+
}
1424+
}
1425+
1426+
#[cfg(bench)]
1427+
mod benches {
1428+
use test::{black_box, Bencher};
1429+
1430+
#[bench]
1431+
fn bech32_parse_address(bh: &mut Bencher) {
1432+
let addr = black_box("bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq");
1433+
1434+
bh.iter(|| {
1435+
let tuple = crate::decode(&addr).expect("address is well formed");
1436+
black_box(&tuple);
1437+
})
1438+
}
1439+
1440+
#[bench]
1441+
fn bech32m_parse_address(bh: &mut Bencher) {
1442+
let addr = black_box("bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg3297");
1443+
1444+
bh.iter(|| {
1445+
let tuple = crate::decode(&addr).expect("address is well formed");
1446+
black_box(&tuple);
1447+
})
1448+
}
1449+
1450+
// Encode with allocation.
1451+
#[bench]
1452+
fn encode_bech32_address(bh: &mut Bencher) {
1453+
let addr = "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq";
1454+
let (hrp, data, variant) = crate::decode(&addr).expect("address is well formed");
1455+
1456+
bh.iter(|| {
1457+
let s = crate::encode(&hrp, &data, variant).expect("failed to encode");
1458+
black_box(&s);
1459+
});
1460+
}
1461+
1462+
// Encode without allocation.
1463+
#[bench]
1464+
fn encode_to_fmt_bech32_address(bh: &mut Bencher) {
1465+
let addr = "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq";
1466+
let (hrp, data, variant) = crate::decode(&addr).expect("address is well formed");
1467+
let mut buf = String::with_capacity(64);
1468+
1469+
bh.iter(|| {
1470+
let res =
1471+
crate::encode_to_fmt(&mut buf, &hrp, &data, variant).expect("failed to encode");
1472+
black_box(&res);
1473+
});
1474+
}
1475+
1476+
// Encode with allocation.
1477+
#[bench]
1478+
fn encode_bech32m_address(bh: &mut Bencher) {
1479+
let addr = "bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg3297";
1480+
let (hrp, data, variant) = crate::decode(&addr).expect("address is well formed");
1481+
1482+
bh.iter(|| {
1483+
let s = crate::encode(&hrp, &data, variant).expect("failed to encode");
1484+
black_box(&s);
1485+
});
1486+
}
1487+
1488+
// Encode without allocation.
1489+
#[bench]
1490+
fn encode_to_fmt_bech32m_address(bh: &mut Bencher) {
1491+
let addr = "bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg3297";
1492+
let (hrp, data, variant) = crate::decode(&addr).expect("address is well formed");
1493+
let mut buf = String::with_capacity(64);
1494+
1495+
bh.iter(|| {
1496+
let res =
1497+
crate::encode_to_fmt(&mut buf, &hrp, &data, variant).expect("failed to encode");
1498+
black_box(&res);
1499+
});
1500+
}
14021501
}

0 commit comments

Comments
 (0)