Use a HashMap instead of a BTreeMap in Scheduler's internals. Doesn't

affect determistic simulation, but yields a crazy speedup. #54

- 8 hours of downtown: 122s to 102s!!!
- prebake: 181s to 160s
This commit is contained in:
Dustin Carlino 2020-10-19 16:30:41 -05:00
parent 82827bd60b
commit 87d233299a
3 changed files with 15 additions and 19 deletions

View File

@ -1,6 +1,7 @@
use std::error::Error;
use std::{cmp, ops};
use ordered_float::NotNan;
use serde::{Deserialize, Serialize};
use crate::{trim_f64, Duration};
@ -17,6 +18,12 @@ impl Ord for Time {
}
}
impl std::hash::Hash for Time {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
NotNan::new(self.0).unwrap().hash(state);
}
}
impl Time {
pub const START_OF_DAY: Time = Time(0.0);

View File

@ -29,7 +29,7 @@ pub struct PandemicModel {
}
// You can schedule callbacks in the future by doing scheduler.push(future time, one of these)
#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord, Clone, Debug)]
pub enum Cmd {
BecomeHospitalized(PersonID),
BecomeQuarantined(PersonID),

View File

@ -1,6 +1,6 @@
use std::cmp::Ordering;
use std::collections::btree_map::Entry;
use std::collections::{BTreeMap, BinaryHeap};
use std::collections::hash_map::Entry;
use std::collections::{BinaryHeap, HashMap};
use serde::{Deserialize, Serialize};
@ -38,7 +38,7 @@ impl Command {
}
}
pub fn to_type(&self) -> CommandType {
fn to_type(&self) -> CommandType {
match self {
Command::SpawnCar(ref create, _) => CommandType::Car(create.vehicle.id),
Command::SpawnPed(ref create) => CommandType::Ped(create.id),
@ -57,8 +57,8 @@ impl Command {
/// A smaller version of Command that satisfies many more properties. Only one Command per
/// CommandType may exist at a time.
#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub enum CommandType {
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord, Clone, Debug)]
enum CommandType {
StartTrip(TripID),
Car(CarID),
CarLaggyHead(CarID),
@ -100,7 +100,7 @@ impl Ord for Item {
#[derive(Clone, Serialize, Deserialize)]
pub struct Scheduler {
items: BinaryHeap<Item>,
queued_commands: BTreeMap<CommandType, (Command, Time)>,
queued_commands: HashMap<CommandType, (Command, Time)>,
latest_time: Time,
last_time: Time,
@ -112,7 +112,7 @@ impl Scheduler {
pub fn new() -> Scheduler {
Scheduler {
items: BinaryHeap::new(),
queued_commands: BTreeMap::new(),
queued_commands: HashMap::new(),
latest_time: Time::START_OF_DAY,
last_time: Time::START_OF_DAY,
delta_times: Histogram::new(),
@ -174,17 +174,6 @@ impl Scheduler {
self.queued_commands.remove(&cmd.to_type());
}
// TODO Should panic if a command of this type isn't scheduled. But currently failing
// unexpectedly.
pub fn must_cancel_by_type(&mut self, cmd: CommandType) {
if self.queued_commands.remove(&cmd).is_none() {
println!(
"must_cancel_by_type({:?}) didn't find a matching command",
cmd
);
}
}
/// This next command might've actually been rescheduled to a later time; the caller won't know
/// that here.
pub fn peek_next_time(&self) -> Option<Time> {