Skip to content

Commit

Permalink
Use 'std::mem::replace' instead of 'clone'.
Browse files Browse the repository at this point in the history
Replacing a value with T::zero() is usually much faster than cloning
and it doesn't affect correctness.
  • Loading branch information
lemmih authored and cuviper committed Jun 23, 2022
1 parent 06d9f21 commit ddba51a
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 2 deletions.
61 changes: 61 additions & 0 deletions benches/bigrational.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#![feature(test)]

extern crate test;

use num_bigint::BigInt;
use num_rational::{BigRational, Ratio};
// use num_traits::{FromPrimitive, Num, One, Zero};
use test::Bencher;

mod rng;
use rng::get_rng;

// allocating 'a' and 'b' is about 70ns.
// allocating BigRational(a,b) is about 970ns.
fn alloc_bench(b: &mut Bencher) {
use rand::RngCore;
let mut rng = get_rng();
b.iter(|| {
let a = BigInt::from(rng.next_u64());
let b = BigInt::from(rng.next_u64());
BigRational::new(a, b)
// (a, b)
});
}

fn alloc_fast_bench(b: &mut Bencher) {
use rand::RngCore;
let mut rng = get_rng();
b.iter(|| {
let a = BigInt::from(rng.next_u64());
let b = BigInt::from(rng.next_u64());
BigRational::new_fast(a, b)
// (a, b)
});
}

fn alloc_u64_bench(b: &mut Bencher) {
use rand::RngCore;
let mut rng = get_rng();
b.iter(|| {
let a = rng.next_u64();
let b = rng.next_u64();
Ratio::new_fast(a, b)
// (a, b)
});
}

#[bench]
fn alloc_0(b: &mut Bencher) {
alloc_bench(b);
}

#[bench]
fn alloc_fast_0(b: &mut Bencher) {
alloc_fast_bench(b);
}

#[bench]
fn alloc_u64_0(b: &mut Bencher) {
alloc_u64_bench(b);
}
38 changes: 38 additions & 0 deletions benches/rng/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use rand::RngCore;

pub(crate) fn get_rng() -> impl RngCore {
XorShiftStar {
a: 0x0123_4567_89AB_CDEF,
}
}

/// Simple `Rng` for benchmarking without additional dependencies
struct XorShiftStar {
a: u64,
}

impl RngCore for XorShiftStar {
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
}

fn next_u64(&mut self) -> u64 {
// https://en.wikipedia.org/wiki/Xorshift#xorshift*
self.a ^= self.a >> 12;
self.a ^= self.a << 25;
self.a ^= self.a >> 27;
self.a.wrapping_mul(0x2545_F491_4F6C_DD1D)
}

fn fill_bytes(&mut self, dest: &mut [u8]) {
for chunk in dest.chunks_mut(8) {
let bytes = self.next_u64().to_le_bytes();
let slice = &bytes[..chunk.len()];
chunk.copy_from_slice(slice)
}
}

fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
Ok(self.fill_bytes(dest))
}
}
9 changes: 7 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,16 @@ impl<T: Clone + Integer> Ratio<T> {
// FIXME(#5992): assignment operator overloads
// self.numer /= g;
// T: Clone + Integer != T: Clone + NumAssign
self.numer = self.numer.clone() / g.clone();
let numer = std::mem::replace(&mut self.numer, T::zero());
self.numer = numer / g.clone();
// self.numer = self.numer.clone() / g.clone();

// FIXME(#5992): assignment operator overloads
// self.denom /= g;
// T: Clone + Integer != T: Clone + NumAssign
self.denom = self.denom.clone() / g;
let denom = std::mem::replace(&mut self.denom, T::zero());
self.denom = denom / g;
// self.denom = self.denom.clone() / g;

// keep denom positive!
if self.denom < T::zero() {
Expand Down

0 comments on commit ddba51a

Please sign in to comment.