mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 03:35:51 +03:00
Use a HashMap to store driving queues. Modest speedup on the downtown
benchmark from ~101s to ~96s. #368
This commit is contained in:
parent
36c1ce02ac
commit
45e6a79e7d
@ -2,32 +2,37 @@ use crate::MultiMap;
|
|||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use std::cmp::Ord;
|
use std::cmp::Ord;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
|
/// Stringifies an object to nicely formatted JSON.
|
||||||
pub fn to_json<T: Serialize>(obj: &T) -> String {
|
pub fn to_json<T: Serialize>(obj: &T) -> String {
|
||||||
serde_json::to_string_pretty(obj).unwrap()
|
serde_json::to_string_pretty(obj).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stringifies an object to terse JSON.
|
||||||
pub fn to_json_terse<T: Serialize>(obj: &T) -> String {
|
pub fn to_json_terse<T: Serialize>(obj: &T) -> String {
|
||||||
serde_json::to_string(obj).unwrap()
|
serde_json::to_string(obj).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deserializes an object from a JSON string.
|
||||||
pub fn from_json<T: DeserializeOwned>(raw: &Vec<u8>) -> Result<T, Box<dyn Error>> {
|
pub fn from_json<T: DeserializeOwned>(raw: &Vec<u8>) -> Result<T, Box<dyn Error>> {
|
||||||
serde_json::from_slice(raw).map_err(|x| x.into())
|
serde_json::from_slice(raw).map_err(|x| x.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deserializes an object from the bincode format.
|
||||||
pub fn from_binary<T: DeserializeOwned>(raw: &Vec<u8>) -> Result<T, Box<dyn Error>> {
|
pub fn from_binary<T: DeserializeOwned>(raw: &Vec<u8>) -> Result<T, Box<dyn Error>> {
|
||||||
bincode::deserialize(raw).map_err(|x| x.into())
|
bincode::deserialize(raw).map_err(|x| x.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of bytes for an object serialized to bincode.
|
||||||
pub fn serialized_size_bytes<T: Serialize>(obj: &T) -> usize {
|
pub fn serialized_size_bytes<T: Serialize>(obj: &T) -> usize {
|
||||||
bincode::serialized_size(obj).unwrap() as usize
|
bincode::serialized_size(obj).unwrap() as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
// For BTreeMaps with struct keys. See https://github.com/serde-rs/json/issues/402.
|
/// Serializes a BTreeMap as a list of tuples. Necessary when the keys are structs; see
|
||||||
|
/// https://github.com/serde-rs/json/issues/402.
|
||||||
pub fn serialize_btreemap<S: Serializer, K: Serialize, V: Serialize>(
|
pub fn serialize_btreemap<S: Serializer, K: Serialize, V: Serialize>(
|
||||||
map: &BTreeMap<K, V>,
|
map: &BTreeMap<K, V>,
|
||||||
s: S,
|
s: S,
|
||||||
@ -35,6 +40,8 @@ pub fn serialize_btreemap<S: Serializer, K: Serialize, V: Serialize>(
|
|||||||
map.iter().collect::<Vec<(_, _)>>().serialize(s)
|
map.iter().collect::<Vec<(_, _)>>().serialize(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deserializes a BTreeMap from a list of tuples. Necessary when the keys are structs; see
|
||||||
|
/// https://github.com/serde-rs/json/issues/402.
|
||||||
pub fn deserialize_btreemap<
|
pub fn deserialize_btreemap<
|
||||||
'de,
|
'de,
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
@ -51,6 +58,35 @@ pub fn deserialize_btreemap<
|
|||||||
Ok(map)
|
Ok(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Serializes a HashMap as a list of tuples, first sorting by the keys. This ensures the
|
||||||
|
/// serialized form is deterministic.
|
||||||
|
pub fn serialize_hashmap<S: Serializer, K: Serialize + Ord, V: Serialize>(
|
||||||
|
map: &HashMap<K, V>,
|
||||||
|
s: S,
|
||||||
|
) -> Result<S::Ok, S::Error> {
|
||||||
|
let mut list: Vec<(&K, &V)> = map.iter().collect();
|
||||||
|
list.sort_by_key(|(k, _)| k.clone());
|
||||||
|
list.serialize(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserializes a HashMap from a list of tuples.
|
||||||
|
pub fn deserialize_hashmap<
|
||||||
|
'de,
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
K: Deserialize<'de> + std::hash::Hash + Eq,
|
||||||
|
V: Deserialize<'de>,
|
||||||
|
>(
|
||||||
|
d: D,
|
||||||
|
) -> Result<HashMap<K, V>, D::Error> {
|
||||||
|
let vec = <Vec<(K, V)>>::deserialize(d)?;
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
for (k, v) in vec {
|
||||||
|
map.insert(k, v);
|
||||||
|
}
|
||||||
|
Ok(map)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serializes a MultiMap.
|
||||||
pub fn serialize_multimap<
|
pub fn serialize_multimap<
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
K: Serialize + Eq + Ord + Clone,
|
K: Serialize + Eq + Ord + Clone,
|
||||||
@ -63,6 +99,7 @@ pub fn serialize_multimap<
|
|||||||
map.raw_map().iter().collect::<Vec<(_, _)>>().serialize(s)
|
map.raw_map().iter().collect::<Vec<(_, _)>>().serialize(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deserializes a MultiMap.
|
||||||
pub fn deserialize_multimap<
|
pub fn deserialize_multimap<
|
||||||
'de,
|
'de,
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
@ -81,6 +118,8 @@ pub fn deserialize_multimap<
|
|||||||
Ok(map)
|
Ok(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Serializes a `usize` as a `u32` to save space. Useful when you need `usize` for indexing, but
|
||||||
|
/// the values don't exceed 2^32.
|
||||||
pub fn serialize_usize<S: Serializer>(x: &usize, s: S) -> Result<S::Ok, S::Error> {
|
pub fn serialize_usize<S: Serializer>(x: &usize, s: S) -> Result<S::Ok, S::Error> {
|
||||||
if let Ok(x) = u32::try_from(*x) {
|
if let Ok(x) = u32::try_from(*x) {
|
||||||
x.serialize(s)
|
x.serialize(s)
|
||||||
@ -89,6 +128,7 @@ pub fn serialize_usize<S: Serializer>(x: &usize, s: S) -> Result<S::Ok, S::Error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deserializes a `usize` from a `u32`.
|
||||||
pub fn deserialize_usize<'de, D: Deserializer<'de>>(d: D) -> Result<usize, D::Error> {
|
pub fn deserialize_usize<'de, D: Deserializer<'de>>(d: D) -> Result<usize, D::Error> {
|
||||||
let x = <u32>::deserialize(d)?;
|
let x = <u32>::deserialize(d)?;
|
||||||
Ok(x as usize)
|
Ok(x as usize)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::collections::{BTreeMap, BTreeSet, HashSet, VecDeque};
|
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use abstutil::{deserialize_btreemap, serialize_btreemap, FixedMap, IndexableKey};
|
use abstutil::{deserialize_hashmap, serialize_hashmap, FixedMap, IndexableKey};
|
||||||
use geom::{Distance, Duration, PolyLine, Speed, Time};
|
use geom::{Distance, Duration, PolyLine, Speed, Time};
|
||||||
use map_model::{LaneID, Map, Path, PathStep, Traversable};
|
use map_model::{LaneID, Map, Path, PathStep, Traversable};
|
||||||
|
|
||||||
@ -30,11 +30,14 @@ pub struct DrivingSimState {
|
|||||||
// gain much faster lookup, which has shown dramatic speedups in the scenarios being run so
|
// gain much faster lookup, which has shown dramatic speedups in the scenarios being run so
|
||||||
// far.
|
// far.
|
||||||
cars: FixedMap<CarID, Car>,
|
cars: FixedMap<CarID, Car>,
|
||||||
|
// Note this uses a HashMap for faster lookup. Although the order of iterating over the HashMap
|
||||||
|
// is random, determinism in the simulation is preserved, because nothing iterates over
|
||||||
|
// everything.
|
||||||
#[serde(
|
#[serde(
|
||||||
serialize_with = "serialize_btreemap",
|
serialize_with = "serialize_hashmap",
|
||||||
deserialize_with = "deserialize_btreemap"
|
deserialize_with = "deserialize_hashmap"
|
||||||
)]
|
)]
|
||||||
queues: BTreeMap<Traversable, Queue>,
|
queues: HashMap<Traversable, Queue>,
|
||||||
events: Vec<Event>,
|
events: Vec<Event>,
|
||||||
|
|
||||||
recalc_lanechanging: bool,
|
recalc_lanechanging: bool,
|
||||||
@ -50,7 +53,7 @@ impl DrivingSimState {
|
|||||||
pub fn new(map: &Map, opts: &SimOptions) -> DrivingSimState {
|
pub fn new(map: &Map, opts: &SimOptions) -> DrivingSimState {
|
||||||
let mut sim = DrivingSimState {
|
let mut sim = DrivingSimState {
|
||||||
cars: FixedMap::new(),
|
cars: FixedMap::new(),
|
||||||
queues: BTreeMap::new(),
|
queues: HashMap::new(),
|
||||||
events: Vec::new(),
|
events: Vec::new(),
|
||||||
recalc_lanechanging: opts.recalc_lanechanging,
|
recalc_lanechanging: opts.recalc_lanechanging,
|
||||||
handle_uber_turns: opts.handle_uber_turns,
|
handle_uber_turns: opts.handle_uber_turns,
|
||||||
@ -217,7 +220,7 @@ impl DrivingSimState {
|
|||||||
|
|
||||||
if !need_distances {
|
if !need_distances {
|
||||||
// We need to mutate two different cars in one case. To avoid fighting the borrow
|
// We need to mutate two different cars in one case. To avoid fighting the borrow
|
||||||
// checker, temporarily move one of them out of the BTreeMap.
|
// checker, temporarily move one of them out of the map.
|
||||||
let mut car = self.cars.remove(&id).unwrap();
|
let mut car = self.cars.remove(&id).unwrap();
|
||||||
// Responsibility of update_car to manage scheduling stuff!
|
// Responsibility of update_car to manage scheduling stuff!
|
||||||
need_distances = self.update_car_without_distances(&mut car, now, ctx, transit);
|
need_distances = self.update_car_without_distances(&mut car, now, ctx, transit);
|
||||||
@ -234,7 +237,7 @@ impl DrivingSimState {
|
|||||||
let idx = dists.iter().position(|(c, _)| *c == id).unwrap();
|
let idx = dists.iter().position(|(c, _)| *c == id).unwrap();
|
||||||
|
|
||||||
// We need to mutate two different cars in some cases. To avoid fighting the borrow
|
// We need to mutate two different cars in some cases. To avoid fighting the borrow
|
||||||
// checker, temporarily move one of them out of the BTreeMap.
|
// checker, temporarily move one of them out of the map.
|
||||||
let mut car = self.cars.remove(&id).unwrap();
|
let mut car = self.cars.remove(&id).unwrap();
|
||||||
// Responsibility of update_car_with_distances to manage scheduling stuff!
|
// Responsibility of update_car_with_distances to manage scheduling stuff!
|
||||||
if self
|
if self
|
||||||
@ -835,6 +838,7 @@ impl DrivingSimState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Note the ordering of results is non-deterministic!
|
||||||
pub fn get_unzoomed_agents(&self, now: Time, map: &Map) -> Vec<UnzoomedAgent> {
|
pub fn get_unzoomed_agents(&self, now: Time, map: &Map) -> Vec<UnzoomedAgent> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
|
|
||||||
@ -867,6 +871,7 @@ impl DrivingSimState {
|
|||||||
self.cars.contains_key(&id)
|
self.cars.contains_key(&id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Note the ordering of results is non-deterministic!
|
||||||
pub fn get_all_draw_cars(
|
pub fn get_all_draw_cars(
|
||||||
&self,
|
&self,
|
||||||
now: Time,
|
now: Time,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::collections::{BTreeMap, BTreeSet, HashSet};
|
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -289,7 +289,7 @@ impl IntersectionSimState {
|
|||||||
maybe_cars_and_queues: Option<(
|
maybe_cars_and_queues: Option<(
|
||||||
&Car,
|
&Car,
|
||||||
&FixedMap<CarID, Car>,
|
&FixedMap<CarID, Car>,
|
||||||
&mut BTreeMap<Traversable, Queue>,
|
&mut HashMap<Traversable, Queue>,
|
||||||
)>,
|
)>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let req = Request { agent, turn };
|
let req = Request { agent, turn };
|
||||||
@ -660,7 +660,7 @@ impl IntersectionSimState {
|
|||||||
&mut self,
|
&mut self,
|
||||||
req: &Request,
|
req: &Request,
|
||||||
map: &Map,
|
map: &Map,
|
||||||
maybe_cars_and_queues: Option<(&FixedMap<CarID, Car>, &BTreeMap<Traversable, Queue>)>,
|
maybe_cars_and_queues: Option<(&FixedMap<CarID, Car>, &HashMap<Traversable, Queue>)>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let turn = map.get_t(req.turn);
|
let turn = map.get_t(req.turn);
|
||||||
let mut cycle_detected = false;
|
let mut cycle_detected = false;
|
||||||
@ -713,7 +713,7 @@ impl IntersectionSimState {
|
|||||||
fn detect_conflict_cycle(
|
fn detect_conflict_cycle(
|
||||||
&self,
|
&self,
|
||||||
car: CarID,
|
car: CarID,
|
||||||
pair: (&FixedMap<CarID, Car>, &BTreeMap<Traversable, Queue>),
|
pair: (&FixedMap<CarID, Car>, &HashMap<Traversable, Queue>),
|
||||||
) -> Option<HashSet<CarID>> {
|
) -> Option<HashSet<CarID>> {
|
||||||
let (cars, queues) = pair;
|
let (cars, queues) = pair;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::collections::{BTreeMap, BTreeSet, VecDeque};
|
use std::collections::{BTreeSet, HashMap, VecDeque};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ impl Queue {
|
|||||||
&self,
|
&self,
|
||||||
now: Time,
|
now: Time,
|
||||||
cars: &FixedMap<CarID, Car>,
|
cars: &FixedMap<CarID, Car>,
|
||||||
queues: &BTreeMap<Traversable, Queue>,
|
queues: &HashMap<Traversable, Queue>,
|
||||||
) -> Option<(CarID, Distance)> {
|
) -> Option<(CarID, Distance)> {
|
||||||
self.inner_get_last_car_position(now, cars, queues, &mut BTreeSet::new(), None)
|
self.inner_get_last_car_position(now, cars, queues, &mut BTreeSet::new(), None)
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ impl Queue {
|
|||||||
&self,
|
&self,
|
||||||
now: Time,
|
now: Time,
|
||||||
cars: &FixedMap<CarID, Car>,
|
cars: &FixedMap<CarID, Car>,
|
||||||
queues: &BTreeMap<Traversable, Queue>,
|
queues: &HashMap<Traversable, Queue>,
|
||||||
) -> Vec<(CarID, Distance)> {
|
) -> Vec<(CarID, Distance)> {
|
||||||
let mut all_cars = vec![];
|
let mut all_cars = vec![];
|
||||||
self.inner_get_last_car_position(
|
self.inner_get_last_car_position(
|
||||||
@ -70,7 +70,7 @@ impl Queue {
|
|||||||
&self,
|
&self,
|
||||||
now: Time,
|
now: Time,
|
||||||
cars: &FixedMap<CarID, Car>,
|
cars: &FixedMap<CarID, Car>,
|
||||||
queues: &BTreeMap<Traversable, Queue>,
|
queues: &HashMap<Traversable, Queue>,
|
||||||
recursed_queues: &mut BTreeSet<Traversable>,
|
recursed_queues: &mut BTreeSet<Traversable>,
|
||||||
mut intermediate_results: Option<&mut Vec<(CarID, Distance)>>,
|
mut intermediate_results: Option<&mut Vec<(CarID, Distance)>>,
|
||||||
) -> Option<(CarID, Distance)> {
|
) -> Option<(CarID, Distance)> {
|
||||||
@ -204,7 +204,7 @@ impl Queue {
|
|||||||
vehicle_len: Distance,
|
vehicle_len: Distance,
|
||||||
now: Time,
|
now: Time,
|
||||||
cars: &FixedMap<CarID, Car>,
|
cars: &FixedMap<CarID, Car>,
|
||||||
queues: &BTreeMap<Traversable, Queue>,
|
queues: &HashMap<Traversable, Queue>,
|
||||||
) -> Option<usize> {
|
) -> Option<usize> {
|
||||||
if self.laggy_head.is_none() && self.cars.is_empty() {
|
if self.laggy_head.is_none() && self.cars.is_empty() {
|
||||||
return Some(0);
|
return Some(0);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! For vehicles only, not pedestrians. Follows a Path from map_model, but can opportunistically
|
//! For vehicles only, not pedestrians. Follows a Path from map_model, but can opportunistically
|
||||||
//! lane-change to avoid a slow lane, can can handle re-planning to look for available parking.
|
//! lane-change to avoid a slow lane, can can handle re-planning to look for available parking.
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -334,7 +334,7 @@ impl Router {
|
|||||||
|
|
||||||
pub fn opportunistically_lanechange(
|
pub fn opportunistically_lanechange(
|
||||||
&mut self,
|
&mut self,
|
||||||
queues: &BTreeMap<Traversable, Queue>,
|
queues: &HashMap<Traversable, Queue>,
|
||||||
map: &Map,
|
map: &Map,
|
||||||
handle_uber_turns: bool,
|
handle_uber_turns: bool,
|
||||||
) {
|
) {
|
||||||
|
Loading…
Reference in New Issue
Block a user