Implement some minor optimizations to version match (#371)

`Range::intersection` goes from 74.2% to 64.9%, and `sortable_tuple`
goes from 2.3% to 1.5%.
This commit is contained in:
Charlie Marsh 2023-11-08 18:11:40 -08:00 committed by GitHub
parent cfd84d6365
commit 6144de0a7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -8,7 +8,7 @@ use regex::Captures;
use regex::Regex; use regex::Regex;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use std::cmp::Ordering; use std::cmp::{max, Ordering};
#[cfg(feature = "pyo3")] #[cfg(feature = "pyo3")]
use std::collections::hash_map::DefaultHasher; use std::collections::hash_map::DefaultHasher;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
@ -538,20 +538,22 @@ impl Display for Version {
pub(crate) fn compare_release(this: &[usize], other: &[usize]) -> Ordering { pub(crate) fn compare_release(this: &[usize], other: &[usize]) -> Ordering {
// "When comparing release segments with different numbers of components, the shorter segment // "When comparing release segments with different numbers of components, the shorter segment
// is padded out with additional zeros as necessary" // is padded out with additional zeros as necessary"
let iterator: Vec<(&usize, &usize)> = if this.len() < other.len() { for (this, other) in this.iter().chain(iter::repeat(&0)).zip(
this.iter().chain(iter::repeat(&0)).zip(other).collect() other
} else { .iter()
this.iter() .chain(iter::repeat(&0))
.zip(other.iter().chain(iter::repeat(&0))) .take(max(this.len(), other.len())),
.collect() ) {
}; match this.cmp(other) {
Ordering::Less => {
for (a, b) in iterator { return Ordering::Less;
if a != b { }
return a.cmp(b); Ordering::Equal => {}
Ordering::Greater => {
return Ordering::Greater;
}
} }
} }
Ordering::Equal Ordering::Equal
} }
@ -568,23 +570,17 @@ pub(crate) fn compare_release(this: &[usize], other: &[usize]) -> Ordering {
/// correct default Ord implementation /// correct default Ord implementation
fn sortable_tuple( fn sortable_tuple(
version: &Version, version: &Version,
) -> ( ) -> (usize, usize, Option<usize>, usize, Option<&[LocalSegment]>) {
usize,
usize,
Option<usize>,
usize,
Option<Vec<LocalSegment>>,
) {
match (&version.pre, &version.post, &version.dev) { match (&version.pre, &version.post, &version.dev) {
// dev release // dev release
(None, None, Some(n)) => (0, 0, None, *n, version.local.clone()), (None, None, Some(n)) => (0, 0, None, *n, version.local.as_deref()),
// alpha release // alpha release
(Some((PreRelease::Alpha, n)), post, dev) => ( (Some((PreRelease::Alpha, n)), post, dev) => (
1, 1,
*n, *n,
*post, *post,
dev.unwrap_or(usize::MAX), dev.unwrap_or(usize::MAX),
version.local.clone(), version.local.as_deref(),
), ),
// beta release // beta release
(Some((PreRelease::Beta, n)), post, dev) => ( (Some((PreRelease::Beta, n)), post, dev) => (
@ -592,7 +588,7 @@ fn sortable_tuple(
*n, *n,
*post, *post,
dev.unwrap_or(usize::MAX), dev.unwrap_or(usize::MAX),
version.local.clone(), version.local.as_deref(),
), ),
// alpha release // alpha release
(Some((PreRelease::Rc, n)), post, dev) => ( (Some((PreRelease::Rc, n)), post, dev) => (
@ -600,17 +596,17 @@ fn sortable_tuple(
*n, *n,
*post, *post,
dev.unwrap_or(usize::MAX), dev.unwrap_or(usize::MAX),
version.local.clone(), version.local.as_deref(),
), ),
// final release // final release
(None, None, None) => (4, 0, None, 0, version.local.clone()), (None, None, None) => (4, 0, None, 0, version.local.as_deref()),
// post release // post release
(None, Some(post), dev) => ( (None, Some(post), dev) => (
5, 5,
0, 0,
Some(*post), Some(*post),
dev.unwrap_or(usize::MAX), dev.unwrap_or(usize::MAX),
version.local.clone(), version.local.as_deref(),
), ),
} }
} }
@ -649,8 +645,14 @@ impl Ord for Version {
/// < 1.0b2.post345.dev456 < 1.0b2.post345 < 1.0b2-346 < 1.0c1.dev456 < 1.0c1 < 1.0rc2 < 1.0c3 /// < 1.0b2.post345.dev456 < 1.0b2.post345 < 1.0b2-346 < 1.0c1.dev456 < 1.0c1 < 1.0rc2 < 1.0c3
/// < 1.0 < 1.0.post456.dev34 < 1.0.post456 /// < 1.0 < 1.0.post456.dev34 < 1.0.post456
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
if self.epoch != other.epoch { match self.epoch.cmp(&other.epoch) {
return self.epoch.cmp(&other.epoch); Ordering::Less => {
return Ordering::Less;
}
Ordering::Equal => {}
Ordering::Greater => {
return Ordering::Greater;
}
} }
match compare_release(&self.release, &other.release) { match compare_release(&self.release, &other.release) {
@ -662,6 +664,7 @@ impl Ord for Version {
return Ordering::Greater; return Ordering::Greater;
} }
} }
// release is equal, so compare the other parts // release is equal, so compare the other parts
sortable_tuple(self).cmp(&sortable_tuple(other)) sortable_tuple(self).cmp(&sortable_tuple(other))
} }