/* * Copyright 2017 Gianmarco Garrisi and contributors * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version, or (at your option) under the terms * of the Mozilla Public License version 2.0. * * ---- * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * ---- * * This Source Code Form is subject to the terms of the Mozilla Public License, * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at http://mozilla.org/MPL/2.0/. * */ #![cfg_attr(feature = "benchmarks", feature(test))] #[cfg(all(test, feature = "benchmarks"))] mod benchmarks { extern crate test; use hashbrown::hash_map::DefaultHashBuilder; use priority_queue::{DoublePriorityQueue, PriorityQueue}; use test::{black_box, Bencher}; #[bench] fn push_and_pop(b: &mut Bencher) { type PqType = PriorityQueue; let mut pq: PqType = PriorityQueue::new(); b.iter(|| { pq.push(black_box(0), black_box(0)); assert_eq![pq.pop().unwrap().1, 0]; }); } #[bench] fn push_and_pop_double(b: &mut Bencher) { type PqType = DoublePriorityQueue; let mut pq: PqType = DoublePriorityQueue::new(); b.iter(|| { pq.push(black_box(0), black_box(0)); assert_eq![pq.pop_max().unwrap().1, 0]; }); } #[bench] fn push_and_pop_fx(b: &mut Bencher) { let mut pq = PriorityQueue::<_, _, DefaultHashBuilder>::with_default_hasher(); b.iter(|| { pq.push(black_box(0), black_box(0)); assert_eq![pq.pop().unwrap().1, 0]; }); } #[bench] fn push_and_pop_double_fx(b: &mut Bencher) { let mut pq = DoublePriorityQueue::<_, _, DefaultHashBuilder>::with_default_hasher(); b.iter(|| { pq.push(black_box(0), black_box(0)); assert_eq![pq.pop_max().unwrap().1, 0]; }); } //for comparison, using the BinaryHeap #[bench] fn push_and_pop_std(b: &mut Bencher) { use std::collections::BinaryHeap; type PqType = BinaryHeap<(usize, i32)>; let mut pq: PqType = BinaryHeap::new(); b.iter(|| { pq.push((black_box(0), black_box(0))); assert_eq![pq.pop().unwrap().1, 0]; }); } #[bench] fn push_and_pop_on_large_queue(b: &mut Bencher) { type PqType = PriorityQueue; let mut pq: PqType = PriorityQueue::new(); for i in 0..100_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.push(black_box(100_000), black_box(100_000)); assert_eq![pq.pop().unwrap().1, black_box(100_000)]; }); } #[bench] fn push_and_pop_on_large_double_queue(b: &mut Bencher) { type PqType = DoublePriorityQueue; let mut pq: PqType = DoublePriorityQueue::new(); for i in 0..100_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.push(black_box(100_000), black_box(100_000)); assert_eq![pq.pop_max().unwrap().1, black_box(100_000)]; }); } #[bench] fn push_and_pop_min_on_large_double_queue(b: &mut Bencher) { type PqType = DoublePriorityQueue; let mut pq: PqType = DoublePriorityQueue::new(); for i in 0..100_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.push(black_box(0), black_box(0)); assert_eq![pq.pop_min().unwrap().1, black_box(0)]; }); } #[bench] fn push_and_pop_on_large_queue_fx(b: &mut Bencher) { let mut pq = PriorityQueue::<_, _, DefaultHashBuilder>::with_default_hasher(); for i in 0..100_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.push(black_box(100_000), black_box(100_000)); assert_eq![pq.pop().unwrap().1, black_box(100_000)]; }); } #[bench] fn push_and_pop_on_large_double_queue_fx(b: &mut Bencher) { let mut pq = DoublePriorityQueue::<_, _, DefaultHashBuilder>::with_default_hasher(); for i in 0..100_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.push(black_box(100_000), black_box(100_000)); assert_eq![pq.pop_max().unwrap().1, black_box(100_000)]; }); } #[bench] fn push_and_pop_min_on_large_double_queue_fx(b: &mut Bencher) { let mut pq = DoublePriorityQueue::<_, _, DefaultHashBuilder>::with_default_hasher(); for i in 0..100_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.push(black_box(0), black_box(0)); assert_eq![pq.pop_min().unwrap().1, black_box(0)]; }); } #[bench] fn push_and_pop_on_large_queue_std(b: &mut Bencher) { use std::collections::BinaryHeap; type PqType = BinaryHeap<(usize, i32)>; let mut pq: PqType = BinaryHeap::new(); for i in 0..100_000 { pq.push((black_box(i as usize), black_box(i))); } b.iter(|| { pq.push((black_box(100_000), black_box(100_000))); assert_eq![pq.pop().unwrap().1, black_box(100_000)]; }); } #[bench] fn priority_change_on_large_queue_std(b: &mut Bencher) { use std::collections::BinaryHeap; struct Entry(usize, i32); impl Ord for Entry { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.0.cmp(&other.0) } } impl PartialOrd for Entry { fn partial_cmp(&self, other: &Self) -> Option { self.0.partial_cmp(&other.0) } } impl Eq for Entry {} impl PartialEq for Entry { fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } type PqType = BinaryHeap; let mut pq: PqType = BinaryHeap::new(); for i in 0..100_000 { pq.push(Entry(black_box(i as usize), black_box(i))); } b.iter(|| { pq = pq .drain() .map(|Entry(i, p)| { if i == 50_000 { Entry(i, p / 2) } else { Entry(i, p) } }) .collect() }); } #[bench] fn priority_change_on_large_queue(b: &mut Bencher) { type PqType = PriorityQueue; let mut pq: PqType = PriorityQueue::new(); for i in 0..100_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.change_priority_by(&50_000, |p| *p = *p / 2); }); } #[bench] fn priority_change_on_large_double_queue(b: &mut Bencher) { type PqType = DoublePriorityQueue; let mut pq: PqType = DoublePriorityQueue::new(); for i in 0..100_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.change_priority_by(&50_000, |p| *p = *p / 2); }); } #[bench] fn priority_change_on_large_queue_fx(b: &mut Bencher) { let mut pq = PriorityQueue::<_, _, DefaultHashBuilder>::with_default_hasher(); for i in 0..100_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.change_priority_by(&50_000, |p| *p = *p / 2); }); } #[bench] fn priority_change_on_large_double_queue_fx(b: &mut Bencher) { let mut pq = DoublePriorityQueue::<_, _, DefaultHashBuilder>::with_default_hasher(); for i in 0..100_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.change_priority_by(&50_000, |p| *p = *p / 2); }); } #[bench] fn priority_change_on_small_queue_std(b: &mut Bencher) { use std::collections::BinaryHeap; struct Entry(usize, i32); impl Ord for Entry { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.0.cmp(&other.0) } } impl PartialOrd for Entry { fn partial_cmp(&self, other: &Self) -> Option { self.0.partial_cmp(&other.0) } } impl Eq for Entry {} impl PartialEq for Entry { fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } type PqType = BinaryHeap; let mut pq: PqType = BinaryHeap::new(); for i in 0..1_000 { pq.push(Entry(black_box(i as usize), black_box(i))); } b.iter(|| { pq = pq .drain() .map(|Entry(i, p)| { if i == 500 { Entry(i, p / 2) } else { Entry(i, p) } }) .collect() }); } #[bench] fn priority_change_on_small_queue(b: &mut Bencher) { type PqType = PriorityQueue; let mut pq: PqType = PriorityQueue::new(); for i in 0..1_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.change_priority_by(&500, |p| *p = *p / 2); }); } #[bench] fn priority_change_on_small_double_queue(b: &mut Bencher) { type PqType = DoublePriorityQueue; let mut pq: PqType = DoublePriorityQueue::new(); for i in 0..1_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.change_priority_by(&500, |p| *p = *p / 2); }); } #[bench] fn priority_change_on_small_queue_fx(b: &mut Bencher) { let mut pq = PriorityQueue::<_, _, DefaultHashBuilder>::with_default_hasher(); for i in 0..1_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.change_priority_by(&500, |p| *p = *p / 2); }); } #[bench] fn priority_change_on_small_double_queue_fx(b: &mut Bencher) { let mut pq = DoublePriorityQueue::<_, _, DefaultHashBuilder>::with_default_hasher(); for i in 0..1_000 { pq.push(black_box(i as usize), black_box(i)); } b.iter(|| { pq.change_priority_by(&500, |p| *p = *p / 2); }); } }