From c5227b39a683ccacaad7af9fa89ed12173407f26 Mon Sep 17 00:00:00 2001 From: VirtuallyThere Date: Tue, 25 Oct 2022 20:21:46 +0200 Subject: [PATCH] Speed up rarity check while indexing (#702) Replace check for uncommon or better rarity by specialized, more efficient call. This method call contributed for 70% of the time in index_transaction, so it's worth adding a more specialized method. There's more potential here, as self.epoch() can likely be sped up significantly - the binary search still takes an inordinate amount of time. See issue #711. --- src/index.rs | 2 +- src/ordinal.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/index.rs b/src/index.rs index ae3483d996..71a8da1b2d 100644 --- a/src/index.rs +++ b/src/index.rs @@ -525,7 +525,7 @@ impl Index { .pop_front() .ok_or_else(|| anyhow!("insufficient inputs for transaction outputs"))?; - if Ordinal(range.0).rarity() > Rarity::Common { + if !Ordinal(range.0).is_common() { ordinal_to_satpoint.insert( &range.0, &encode_satpoint(SatPoint { diff --git a/src/ordinal.rs b/src/ordinal.rs index fd88e720d1..a97548c0bd 100644 --- a/src/ordinal.rs +++ b/src/ordinal.rs @@ -52,6 +52,14 @@ impl Ordinal { self.into() } + /// `Ordinal::rarity` is expensive and is called frequently when indexing. + /// Ordinal::is_common only checks if self is `Rarity::Common` but is + /// much faster. + pub(crate) fn is_common(self) -> bool { + let epoch = self.epoch(); + (self.0 - epoch.starting_ordinal().0) % epoch.subsidy() != 0 + } + pub(crate) fn name(self) -> String { let mut x = Self::SUPPLY - self.0; let mut name = String::new(); @@ -597,4 +605,23 @@ mod tests { case(Ordinal::LAST.n() / (n + 1)); } } + + #[test] + fn is_common() { + fn case(n: u64) { + assert_eq!( + Ordinal(n).is_common(), + Ordinal(n).rarity() == Rarity::Common + ); + } + + case(0); + case(1); + case(50 * COIN_VALUE - 1); + case(50 * COIN_VALUE); + case(50 * COIN_VALUE + 1); + case(2067187500000000 - 1); + case(2067187500000000); + case(2067187500000000 + 1); + } }