mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 23:15:24 +03:00
making hierarchial progress timer to replace flamegraphs. using in many,
but not all, places
This commit is contained in:
parent
51fa5a0aba
commit
f011f8f56d
@ -21,6 +21,6 @@ pub use io::{
|
||||
write_json,
|
||||
};
|
||||
pub use logs::{format_log_record, LogAdapter};
|
||||
pub use time::{elapsed_seconds, Progress};
|
||||
pub use time::{elapsed_seconds, Timer};
|
||||
|
||||
const PROGRESS_FREQUENCY_SECONDS: f64 = 0.2;
|
||||
|
@ -7,7 +7,7 @@ pub fn elapsed_seconds(since: Instant) -> f64 {
|
||||
(dt.as_secs() as f64) + (f64::from(dt.subsec_nanos()) * 1e-9)
|
||||
}
|
||||
|
||||
pub struct Progress {
|
||||
struct Progress {
|
||||
label: String,
|
||||
processed_items: usize,
|
||||
total_items: usize,
|
||||
@ -16,7 +16,7 @@ pub struct Progress {
|
||||
}
|
||||
|
||||
impl Progress {
|
||||
pub fn new(label: &str, total_items: usize) -> Progress {
|
||||
fn new(label: &str, total_items: usize) -> Progress {
|
||||
Progress {
|
||||
label: label.to_string(),
|
||||
processed_items: 0,
|
||||
@ -26,7 +26,8 @@ impl Progress {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next(&mut self) {
|
||||
// Returns when done
|
||||
fn next(&mut self, padding: String) -> Option<String> {
|
||||
self.processed_items += 1;
|
||||
if self.processed_items > self.total_items {
|
||||
panic!(
|
||||
@ -38,20 +39,116 @@ impl Progress {
|
||||
let done = self.processed_items == self.total_items;
|
||||
if elapsed_seconds(self.last_printed_at) >= PROGRESS_FREQUENCY_SECONDS || done {
|
||||
self.last_printed_at = Instant::now();
|
||||
// TODO blank till end of current line
|
||||
print!(
|
||||
let line = format!(
|
||||
"{}{}: {}/{}... {}s",
|
||||
"\r",
|
||||
padding,
|
||||
self.label,
|
||||
self.processed_items,
|
||||
self.total_items,
|
||||
elapsed_seconds(self.started_at),
|
||||
elapsed_seconds(self.started_at)
|
||||
);
|
||||
// TODO blank till end of current line
|
||||
print!("\r{}", line);
|
||||
if done {
|
||||
println!("");
|
||||
return Some(line);
|
||||
} else {
|
||||
stdout().flush().unwrap();
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
enum StackEntry {
|
||||
TimerSpan(TimerSpan),
|
||||
Progress(Progress),
|
||||
}
|
||||
|
||||
// Hierarchial magic
|
||||
pub struct Timer {
|
||||
results: Vec<String>,
|
||||
stack: Vec<StackEntry>,
|
||||
}
|
||||
|
||||
struct TimerSpan {
|
||||
name: String,
|
||||
started_at: Instant,
|
||||
}
|
||||
|
||||
impl Timer {
|
||||
pub fn new() -> Timer {
|
||||
Timer {
|
||||
results: Vec::new(),
|
||||
stack: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn done(self) {
|
||||
assert!(self.stack.is_empty());
|
||||
println!("");
|
||||
for line in self.results {
|
||||
println!("{}", line);
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
|
||||
pub fn start(&mut self, name: &str) {
|
||||
println!("{}- {}...", " ".repeat(self.stack.len()), name);
|
||||
self.stack.push(StackEntry::TimerSpan(TimerSpan {
|
||||
name: name.to_string(),
|
||||
started_at: Instant::now(),
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn stop(&mut self, name: &str) {
|
||||
let span = match self.stack.pop().unwrap() {
|
||||
StackEntry::TimerSpan(s) => s,
|
||||
StackEntry::Progress(p) => panic!(
|
||||
"stop({}) while a Progress({}, {}/{}) is top of the stack",
|
||||
name, p.label, p.processed_items, p.total_items
|
||||
),
|
||||
};
|
||||
assert_eq!(span.name, name);
|
||||
let line = format!(
|
||||
"{}- {} took {}s",
|
||||
" ".repeat(self.stack.len()),
|
||||
name,
|
||||
elapsed_seconds(span.started_at)
|
||||
);
|
||||
println!("{}", line);
|
||||
self.results.push(line);
|
||||
}
|
||||
|
||||
pub fn start_iter(&mut self, name: &str, total_items: usize) {
|
||||
if total_items == 0 {
|
||||
panic!("Can't start_iter({}, 0)", name);
|
||||
}
|
||||
if let Some(StackEntry::Progress(p)) = self.stack.last() {
|
||||
panic!(
|
||||
"Can't start_iter({}) while Progress({}) is top of the stack",
|
||||
name, p.label
|
||||
);
|
||||
}
|
||||
|
||||
self.stack
|
||||
.push(StackEntry::Progress(Progress::new(name, total_items)));
|
||||
}
|
||||
|
||||
pub fn next(&mut self) {
|
||||
let padding = format!("{} - ", " ".repeat(self.stack.len() - 1));
|
||||
let done = if let Some(StackEntry::Progress(ref mut progress)) = self.stack.last_mut() {
|
||||
if let Some(result) = progress.next(padding) {
|
||||
self.results.push(result);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
panic!("Can't next() while a TimerSpan is top of the stack");
|
||||
};
|
||||
if done {
|
||||
self.stack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,6 @@
|
||||
- run clippy everywhere
|
||||
- presubmit script
|
||||
- also enforce consistent style (import order, extern crate only in mod.rs or lib.rs, derive order, struct initialization order)
|
||||
- profiling
|
||||
- https://github.com/TyOverby/flame
|
||||
|
||||
## Conga line idea
|
||||
|
||||
|
@ -12,7 +12,6 @@ cpuprofiler = "0.0.3"
|
||||
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
|
||||
downcast = "0.9.2"
|
||||
ezgui = { path = "../ezgui" }
|
||||
flame = "0.2.2"
|
||||
generator = "0.6"
|
||||
geo = "0.9.1"
|
||||
geom = { path = "../geom" }
|
||||
|
@ -9,7 +9,6 @@ extern crate dimensioned;
|
||||
#[macro_use]
|
||||
extern crate downcast;
|
||||
extern crate ezgui;
|
||||
extern crate flame;
|
||||
#[macro_use]
|
||||
extern crate generator;
|
||||
extern crate geo;
|
||||
|
@ -15,13 +15,17 @@ pub struct NeighborhoodSummary {
|
||||
}
|
||||
|
||||
impl NeighborhoodSummary {
|
||||
pub fn new(map: &Map) -> NeighborhoodSummary {
|
||||
pub fn new(map: &Map, timer: &mut abstutil::Timer) -> NeighborhoodSummary {
|
||||
let neighborhoods = abstutil::load_all_objects("neighborhoods", map.get_name());
|
||||
timer.start_iter("precompute neighborhood members", neighborhoods.len());
|
||||
NeighborhoodSummary {
|
||||
regions: abstutil::load_all_objects("neighborhoods", map.get_name())
|
||||
regions: neighborhoods
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(idx, (_, n))| Region::new(idx, n, map))
|
||||
.collect(),
|
||||
.map(|(idx, (_, n))| {
|
||||
timer.next();
|
||||
Region::new(idx, n, map)
|
||||
}).collect(),
|
||||
active: false,
|
||||
last_summary: None,
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
use abstutil::Progress;
|
||||
use aabb_quadtree::geom::{Point, Rect};
|
||||
use aabb_quadtree::QuadTree;
|
||||
use abstutil::Timer;
|
||||
use control::ControlMap;
|
||||
use geom::{Bounds, Pt2D};
|
||||
use kml::{ExtraShape, ExtraShapeID};
|
||||
@ -43,11 +43,16 @@ pub struct DrawMap {
|
||||
}
|
||||
|
||||
impl DrawMap {
|
||||
pub fn new(map: &Map, control_map: &ControlMap, raw_extra_shapes: Vec<ExtraShape>) -> DrawMap {
|
||||
pub fn new(
|
||||
map: &Map,
|
||||
control_map: &ControlMap,
|
||||
raw_extra_shapes: Vec<ExtraShape>,
|
||||
timer: &mut Timer,
|
||||
) -> DrawMap {
|
||||
let mut lanes: Vec<DrawLane> = Vec::new();
|
||||
let mut progress = Progress::new("make DrawLanes", map.all_lanes().len());
|
||||
timer.start_iter("make DrawLanes", map.all_lanes().len());
|
||||
for l in map.all_lanes() {
|
||||
progress.next();
|
||||
timer.next();
|
||||
lanes.push(DrawLane::new(l, map, control_map));
|
||||
}
|
||||
|
||||
@ -89,6 +94,7 @@ impl DrawMap {
|
||||
let bounds = map.get_bounds();
|
||||
let map_bbox = get_bbox(bounds);
|
||||
|
||||
timer.start("create quadtree");
|
||||
let mut quadtree = QuadTree::default(map_bbox);
|
||||
// TODO use iter chain if everything was boxed as a renderable...
|
||||
for obj in &lanes {
|
||||
@ -112,6 +118,7 @@ impl DrawMap {
|
||||
for obj in &areas {
|
||||
quadtree.insert_with_box(obj.get_id(), get_bbox(obj.get_bounds()));
|
||||
}
|
||||
timer.stop("create quadtree");
|
||||
|
||||
DrawMap {
|
||||
lanes,
|
||||
|
@ -7,7 +7,6 @@ use colors::ColorScheme;
|
||||
use control::ControlMap;
|
||||
//use cpuprofiler;
|
||||
use ezgui::{Canvas, Color, EventLoopMode, GfxCtx, Text, UserInput, BOTTOM_LEFT, GUI};
|
||||
use flame;
|
||||
use kml;
|
||||
use map_model::{IntersectionID, Map};
|
||||
use objects::{Ctx, ID, ROOT_MENU};
|
||||
@ -232,27 +231,27 @@ impl PluginsPerMap {
|
||||
|
||||
impl PerMapUI {
|
||||
pub fn new(flags: SimFlags, kml: &Option<String>) -> (PerMapUI, PluginsPerMap) {
|
||||
flame::start("setup");
|
||||
let (map, control_map, sim) = sim::load(flags.clone(), Some(sim::Tick::from_seconds(30)));
|
||||
let mut timer = abstutil::Timer::new();
|
||||
timer.start("PerMapUI setup");
|
||||
|
||||
let (map, control_map, sim) =
|
||||
sim::load(flags.clone(), Some(sim::Tick::from_seconds(30)), &mut timer);
|
||||
let extra_shapes = if let Some(path) = kml {
|
||||
kml::load(&path, &map.get_gps_bounds()).expect("Couldn't load extra KML shapes")
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
flame::start("draw_map");
|
||||
let draw_map = DrawMap::new(&map, &control_map, extra_shapes);
|
||||
flame::end("draw_map");
|
||||
timer.start("draw_map");
|
||||
let draw_map = DrawMap::new(&map, &control_map, extra_shapes, &mut timer);
|
||||
timer.stop("draw_map");
|
||||
|
||||
flame::start("steepness_viz");
|
||||
let steepness_viz = plugins::steep::SteepnessVisualizer::new(&map);
|
||||
flame::end("steepness_viz");
|
||||
flame::start("neighborhood_summary");
|
||||
let neighborhood_summary = plugins::neighborhood_summary::NeighborhoodSummary::new(&map);
|
||||
flame::end("neighborhood_summary");
|
||||
let neighborhood_summary =
|
||||
plugins::neighborhood_summary::NeighborhoodSummary::new(&map, &mut timer);
|
||||
|
||||
flame::end("setup");
|
||||
flame::dump_stdout();
|
||||
timer.stop("PerMapUI setup");
|
||||
timer.done();
|
||||
|
||||
let state = PerMapUI {
|
||||
map,
|
||||
|
@ -7,7 +7,6 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
|
||||
aabb-quadtree = "0.1.0"
|
||||
abstutil = { path = "../abstutil" }
|
||||
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
|
||||
flame = "0.2.2"
|
||||
geo = "0.9.1"
|
||||
geom = { path = "../geom" }
|
||||
gtfs = { path = "../gtfs" }
|
||||
|
@ -1,7 +1,6 @@
|
||||
extern crate aabb_quadtree;
|
||||
extern crate abstutil;
|
||||
extern crate dimensioned;
|
||||
extern crate flame;
|
||||
extern crate geo;
|
||||
extern crate geom;
|
||||
extern crate gtfs;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use abstutil::Progress;
|
||||
use abstutil::Timer;
|
||||
use dimensioned::si;
|
||||
use geom::{Bounds, HashablePt2D, Line, PolyLine, Pt2D};
|
||||
use make::sidewalk_finder::find_sidewalk_points;
|
||||
@ -12,13 +12,15 @@ pub fn make_all_buildings(
|
||||
gps_bounds: &Bounds,
|
||||
bounds: &Bounds,
|
||||
lanes: &Vec<Lane>,
|
||||
timer: &mut Timer,
|
||||
) {
|
||||
timer.start("convert buildings");
|
||||
let mut pts_per_bldg: Vec<Vec<Pt2D>> = Vec::new();
|
||||
let mut center_per_bldg: Vec<HashablePt2D> = Vec::new();
|
||||
let mut query: HashSet<HashablePt2D> = HashSet::new();
|
||||
let mut progress = Progress::new("get building center points", input.len());
|
||||
timer.start_iter("get building center points", input.len());
|
||||
for b in input {
|
||||
progress.next();
|
||||
timer.next();
|
||||
let pts = b
|
||||
.points
|
||||
.iter()
|
||||
@ -31,11 +33,11 @@ pub fn make_all_buildings(
|
||||
}
|
||||
|
||||
// Skip buildings that're too far away from their sidewalk
|
||||
let sidewalk_pts = find_sidewalk_points(bounds, query, lanes, 100.0 * si::M);
|
||||
let sidewalk_pts = find_sidewalk_points(bounds, query, lanes, 100.0 * si::M, timer);
|
||||
|
||||
let mut progress = Progress::new("create building front paths", pts_per_bldg.len());
|
||||
timer.start_iter("create building front paths", pts_per_bldg.len());
|
||||
for (idx, points) in pts_per_bldg.into_iter().enumerate() {
|
||||
progress.next();
|
||||
timer.next();
|
||||
let bldg_center = center_per_bldg[idx];
|
||||
if let Some((sidewalk, dist_along)) = sidewalk_pts.get(&bldg_center) {
|
||||
let (sidewalk_pt, _) = lanes[sidewalk.0].dist_along(*dist_along);
|
||||
@ -64,6 +66,7 @@ pub fn make_all_buildings(
|
||||
discarded
|
||||
);
|
||||
}
|
||||
timer.stop("convert buildings");
|
||||
}
|
||||
|
||||
// Adjust the path to start on the building's border, not center
|
||||
|
@ -1,3 +1,4 @@
|
||||
use abstutil::Timer;
|
||||
use dimensioned::si;
|
||||
use geom::{Bounds, HashablePt2D, Pt2D};
|
||||
use gtfs;
|
||||
@ -14,7 +15,9 @@ pub fn make_bus_stops(
|
||||
bus_routes: &Vec<gtfs::Route>,
|
||||
gps_bounds: &Bounds,
|
||||
bounds: &Bounds,
|
||||
timer: &mut Timer,
|
||||
) -> (BTreeMap<BusStopID, BusStop>, Vec<BusRoute>) {
|
||||
timer.start("make bus stops");
|
||||
let mut bus_stop_pts: HashSet<HashablePt2D> = HashSet::new();
|
||||
let mut route_lookups: MultiMap<String, HashablePt2D> = MultiMap::new();
|
||||
for route in bus_routes {
|
||||
@ -29,7 +32,7 @@ pub fn make_bus_stops(
|
||||
|
||||
let mut stops_per_sidewalk: MultiMap<LaneID, (si::Meter<f64>, HashablePt2D)> = MultiMap::new();
|
||||
for (pt, (lane, dist_along)) in
|
||||
find_sidewalk_points(bounds, bus_stop_pts, lanes, 10.0 * si::M).iter()
|
||||
find_sidewalk_points(bounds, bus_stop_pts, lanes, 10.0 * si::M, timer).iter()
|
||||
{
|
||||
stops_per_sidewalk.insert(*lane, (*dist_along, *pt));
|
||||
}
|
||||
@ -95,6 +98,7 @@ pub fn make_bus_stops(
|
||||
});
|
||||
}
|
||||
}
|
||||
timer.stop("make bus stops");
|
||||
(bus_stops, routes)
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
use abstutil::Timer;
|
||||
use dimensioned::si;
|
||||
use geom::{Bounds, HashablePt2D, Pt2D};
|
||||
use make::sidewalk_finder::find_sidewalk_points;
|
||||
@ -11,7 +12,9 @@ pub fn make_all_parcels(
|
||||
gps_bounds: &Bounds,
|
||||
bounds: &Bounds,
|
||||
lanes: &Vec<Lane>,
|
||||
timer: &mut Timer,
|
||||
) {
|
||||
timer.start("convert parcels");
|
||||
let mut pts_per_parcel: Vec<Vec<Pt2D>> = Vec::new();
|
||||
let mut center_per_parcel: Vec<HashablePt2D> = Vec::new();
|
||||
let mut query: HashSet<HashablePt2D> = HashSet::new();
|
||||
@ -28,7 +31,7 @@ pub fn make_all_parcels(
|
||||
}
|
||||
|
||||
// Trim parcels that are too far away from the nearest sidewalk
|
||||
let sidewalk_pts = find_sidewalk_points(bounds, query, lanes, 100.0 * si::M);
|
||||
let sidewalk_pts = find_sidewalk_points(bounds, query, lanes, 100.0 * si::M, timer);
|
||||
|
||||
for (idx, center) in center_per_parcel.into_iter().enumerate() {
|
||||
if sidewalk_pts.contains_key(¢er) {
|
||||
@ -47,4 +50,5 @@ pub fn make_all_parcels(
|
||||
discarded
|
||||
);
|
||||
}
|
||||
timer.stop("convert parcels");
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use aabb_quadtree::geom::{Point, Rect};
|
||||
use aabb_quadtree::QuadTree;
|
||||
use abstutil::Progress;
|
||||
use abstutil::Timer;
|
||||
use dimensioned::si;
|
||||
use geo;
|
||||
use geo::prelude::{ClosestPoint, EuclideanDistance};
|
||||
@ -16,13 +16,18 @@ pub fn find_sidewalk_points(
|
||||
pts: HashSet<HashablePt2D>,
|
||||
lanes: &Vec<Lane>,
|
||||
max_dist_away: si::Meter<f64>,
|
||||
timer: &mut Timer,
|
||||
) -> HashMap<HashablePt2D, (LaneID, si::Meter<f64>)> {
|
||||
if pts.is_empty() {
|
||||
return HashMap::new();
|
||||
}
|
||||
|
||||
// Convert all sidewalks to LineStrings and index them with a quadtree.
|
||||
let mut lane_lines_quadtree: QuadTree<usize> = QuadTree::default(get_bbox(bounds));
|
||||
let mut lane_lines: Vec<(LaneID, geo::LineString<f64>)> = Vec::new();
|
||||
let mut progress = Progress::new("lanes to LineStrings", lanes.len());
|
||||
timer.start_iter("lanes to LineStrings", lanes.len());
|
||||
for l in lanes {
|
||||
progress.next();
|
||||
timer.next();
|
||||
if l.is_sidewalk() {
|
||||
lane_lines.push((l.id, lane_to_line_string(l)));
|
||||
lane_lines_quadtree.insert_with_box(lane_lines.len() - 1, lane_to_rect(l));
|
||||
@ -32,9 +37,9 @@ pub fn find_sidewalk_points(
|
||||
// For each point, find the closest point to any sidewalk, using the quadtree to prune the
|
||||
// search.
|
||||
let mut results: HashMap<HashablePt2D, (LaneID, si::Meter<f64>)> = HashMap::new();
|
||||
let mut progress = Progress::new("find closest sidewalk point", pts.len());
|
||||
timer.start_iter("find closest sidewalk point", pts.len());
|
||||
for query_pt in pts {
|
||||
progress.next();
|
||||
timer.next();
|
||||
let query_geo_pt = geo::Point::new(query_pt.x(), query_pt.y());
|
||||
let query_bbox = Rect {
|
||||
top_left: Point {
|
||||
|
@ -1,9 +1,8 @@
|
||||
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
use abstutil;
|
||||
use abstutil::{Error, Progress};
|
||||
use abstutil::{Error, Timer};
|
||||
use edits::RoadEdits;
|
||||
use flame;
|
||||
use geom::{Bounds, HashablePt2D, LonLat, PolyLine, Pt2D};
|
||||
use make;
|
||||
use raw_data;
|
||||
@ -35,13 +34,11 @@ pub struct Map {
|
||||
}
|
||||
|
||||
impl Map {
|
||||
pub fn new(path: &str, road_edits: RoadEdits) -> Result<Map, io::Error> {
|
||||
// TODO I think I want something a bit different than flame:
|
||||
// - Print as each phase occurs
|
||||
// - Print with nicely formatted durations
|
||||
flame::start("read raw_data");
|
||||
pub fn new(path: &str, road_edits: RoadEdits, timer: &mut Timer) -> Result<Map, io::Error> {
|
||||
// TODO use read_binary's timer magic, not this
|
||||
timer.start("read raw_data");
|
||||
let data: raw_data::Map = abstutil::read_binary(path)?;
|
||||
flame::end("read raw_data");
|
||||
timer.stop("read raw_data");
|
||||
Ok(Map::create_from_raw(
|
||||
path::Path::new(path)
|
||||
.file_stem()
|
||||
@ -51,10 +48,17 @@ impl Map {
|
||||
.unwrap(),
|
||||
data,
|
||||
road_edits,
|
||||
timer,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn create_from_raw(name: String, data: raw_data::Map, road_edits: RoadEdits) -> Map {
|
||||
pub fn create_from_raw(
|
||||
name: String,
|
||||
data: raw_data::Map,
|
||||
road_edits: RoadEdits,
|
||||
timer: &mut Timer,
|
||||
) -> Map {
|
||||
timer.start("raw_map to Map");
|
||||
let gps_bounds = data.get_gps_bounds();
|
||||
let bounds = gps_to_map_bounds(&gps_bounds);
|
||||
let mut m = Map {
|
||||
@ -90,7 +94,9 @@ impl Map {
|
||||
}
|
||||
|
||||
let mut counter = 0;
|
||||
timer.start_iter("expand roads to lanes", data.roads.len());
|
||||
for (idx, r) in data.roads.iter().enumerate() {
|
||||
timer.next();
|
||||
let road_id = RoadID(idx);
|
||||
let road_center_pts = PolyLine::new(
|
||||
r.points
|
||||
@ -158,9 +164,9 @@ impl Map {
|
||||
}
|
||||
}
|
||||
|
||||
let mut progress = Progress::new("trim lanes at each intersection", m.intersections.len());
|
||||
timer.start_iter("trim lanes at each intersection", m.intersections.len());
|
||||
for i in &m.intersections {
|
||||
progress.next();
|
||||
timer.next();
|
||||
make::trim_lines(&mut m.lanes, i);
|
||||
if i.incoming_lanes.is_empty() && i.outgoing_lanes.is_empty() {
|
||||
panic!("{:?} is orphaned!", i);
|
||||
@ -173,6 +179,7 @@ impl Map {
|
||||
&data.bus_routes,
|
||||
&gps_bounds,
|
||||
&bounds,
|
||||
timer,
|
||||
);
|
||||
m.bus_stops = stops;
|
||||
|
||||
@ -186,30 +193,26 @@ impl Map {
|
||||
m.intersections[t.parent.0].turns.push(t.id);
|
||||
}
|
||||
|
||||
{
|
||||
let _guard = flame::start_guard(format!("make {} buildings", data.buildings.len()));
|
||||
make::make_all_buildings(
|
||||
&mut m.buildings,
|
||||
&data.buildings,
|
||||
&gps_bounds,
|
||||
&bounds,
|
||||
&m.lanes,
|
||||
);
|
||||
for b in &m.buildings {
|
||||
m.lanes[b.front_path.sidewalk.0].building_paths.push(b.id);
|
||||
}
|
||||
make::make_all_buildings(
|
||||
&mut m.buildings,
|
||||
&data.buildings,
|
||||
&gps_bounds,
|
||||
&bounds,
|
||||
&m.lanes,
|
||||
timer,
|
||||
);
|
||||
for b in &m.buildings {
|
||||
m.lanes[b.front_path.sidewalk.0].building_paths.push(b.id);
|
||||
}
|
||||
|
||||
{
|
||||
let _guard = flame::start_guard(format!("make {} parcels", data.parcels.len()));
|
||||
make::make_all_parcels(
|
||||
&mut m.parcels,
|
||||
&data.parcels,
|
||||
&gps_bounds,
|
||||
&bounds,
|
||||
&m.lanes,
|
||||
);
|
||||
}
|
||||
make::make_all_parcels(
|
||||
&mut m.parcels,
|
||||
&data.parcels,
|
||||
&gps_bounds,
|
||||
&bounds,
|
||||
&m.lanes,
|
||||
timer,
|
||||
);
|
||||
|
||||
for (idx, a) in data.areas.iter().enumerate() {
|
||||
m.areas.push(Area {
|
||||
@ -225,11 +228,9 @@ impl Map {
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let _guard = flame::start_guard(format!("verify {} bus routes", routes.len()));
|
||||
m.bus_routes = make::verify_bus_routes(&m, routes);
|
||||
}
|
||||
m.bus_routes = make::verify_bus_routes(&m, routes);
|
||||
|
||||
timer.stop("raw_map to Map");
|
||||
m
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@ backtrace = "0.3.9"
|
||||
control = { path = "../control" }
|
||||
derivative = "1.0.0"
|
||||
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
|
||||
flame = "0.2.2"
|
||||
geom = { path = "../geom" }
|
||||
lazy_static = "1.1.0"
|
||||
log = "0.4.5"
|
||||
|
@ -1,6 +1,5 @@
|
||||
use abstutil;
|
||||
use control::ControlMap;
|
||||
use flame;
|
||||
use map_model::{BuildingID, BusRoute, BusStopID, LaneID, Map, RoadID};
|
||||
use std::collections::{BTreeSet, VecDeque};
|
||||
use {
|
||||
@ -40,14 +39,18 @@ impl SimFlags {
|
||||
}
|
||||
|
||||
// Convenience method to setup everything.
|
||||
pub fn load(flags: SimFlags, savestate_every: Option<Tick>) -> (Map, ControlMap, Sim) {
|
||||
pub fn load(
|
||||
flags: SimFlags,
|
||||
savestate_every: Option<Tick>,
|
||||
timer: &mut abstutil::Timer,
|
||||
) -> (Map, ControlMap, Sim) {
|
||||
if flags.load.contains("data/save/") {
|
||||
assert_eq!(flags.edits_name, "no_edits");
|
||||
|
||||
info!("Resuming from {}", flags.load);
|
||||
flame::start("read sim savestate");
|
||||
timer.start("read sim savestate");
|
||||
let sim: Sim = abstutil::read_json(&flags.load).expect("loading sim state failed");
|
||||
flame::end("read sim savestate");
|
||||
timer.stop("read sim savestate");
|
||||
|
||||
let edits: MapEdits = abstutil::read_json(&format!(
|
||||
"../data/edits/{}/{}.json",
|
||||
@ -60,7 +63,7 @@ pub fn load(flags: SimFlags, savestate_every: Option<Tick>) -> (Map, ControlMap,
|
||||
sim.map_name, sim.edits_name
|
||||
)).unwrap_or_else(|_| {
|
||||
let map_path = format!("../data/raw_maps/{}.abst", sim.map_name);
|
||||
Map::new(&map_path, edits.road_edits.clone())
|
||||
Map::new(&map_path, edits.road_edits.clone(), timer)
|
||||
.expect(&format!("Couldn't load map from {}", map_path))
|
||||
});
|
||||
let control_map = ControlMap::new(&map, edits.stop_signs, edits.traffic_signals);
|
||||
@ -77,7 +80,7 @@ pub fn load(flags: SimFlags, savestate_every: Option<Tick>) -> (Map, ControlMap,
|
||||
scenario.map_name, edits.edits_name
|
||||
)).unwrap_or_else(|_| {
|
||||
let map_path = format!("../data/raw_maps/{}.abst", scenario.map_name);
|
||||
Map::new(&map_path, edits.road_edits.clone())
|
||||
Map::new(&map_path, edits.road_edits.clone(), timer)
|
||||
.expect(&format!("Couldn't load map from {}", map_path))
|
||||
});
|
||||
let control_map = ControlMap::new(&map, edits.stop_signs, edits.traffic_signals);
|
||||
@ -99,19 +102,21 @@ pub fn load(flags: SimFlags, savestate_every: Option<Tick>) -> (Map, ControlMap,
|
||||
.to_string();
|
||||
info!("Loading map {}", flags.load);
|
||||
let edits = load_edits(&map_name, &flags);
|
||||
let map = Map::new(&flags.load, edits.road_edits.clone()).expect("Couldn't load map");
|
||||
let map =
|
||||
Map::new(&flags.load, edits.road_edits.clone(), timer).expect("Couldn't load map");
|
||||
let control_map = ControlMap::new(&map, edits.stop_signs, edits.traffic_signals);
|
||||
flame::start("create sim");
|
||||
timer.start("create sim");
|
||||
let sim = Sim::new(&map, flags.run_name, flags.rng_seed, savestate_every);
|
||||
flame::end("create sim");
|
||||
timer.stop("create sim");
|
||||
(map, control_map, sim)
|
||||
} else if flags.load.contains("data/maps/") {
|
||||
assert_eq!(flags.edits_name, "no_edits");
|
||||
|
||||
info!("Loading map {}", flags.load);
|
||||
flame::start("load binary map");
|
||||
// TODO dont do this
|
||||
timer.start("load binary map");
|
||||
let map: Map = abstutil::read_binary(&flags.load).expect("Couldn't load map");
|
||||
flame::end("load binary map");
|
||||
timer.stop("load binary map");
|
||||
// TODO Bit sad to load edits to reconstitute ControlMap, but this is necessary right now
|
||||
let edits: MapEdits = abstutil::read_json(&format!(
|
||||
"../data/edits/{}/{}.json",
|
||||
@ -119,9 +124,9 @@ pub fn load(flags: SimFlags, savestate_every: Option<Tick>) -> (Map, ControlMap,
|
||||
map.get_road_edits().edits_name
|
||||
)).unwrap();
|
||||
let control_map = ControlMap::new(&map, edits.stop_signs, edits.traffic_signals);
|
||||
flame::start("create sim");
|
||||
timer.start("create sim");
|
||||
let sim = Sim::new(&map, flags.run_name, flags.rng_seed, savestate_every);
|
||||
flame::end("create sim");
|
||||
timer.stop("create sim");
|
||||
(map, control_map, sim)
|
||||
} else {
|
||||
panic!("Don't know how to load {}", flags.load);
|
||||
|
@ -6,7 +6,6 @@ extern crate control;
|
||||
#[macro_use]
|
||||
extern crate derivative;
|
||||
extern crate dimensioned;
|
||||
extern crate flame;
|
||||
extern crate geom;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
Loading…
Reference in New Issue
Block a user