record stack traces

This commit is contained in:
Dustin Carlino 2018-09-05 17:13:26 -07:00
parent 0276dd54aa
commit c5c00d5740
7 changed files with 64 additions and 20 deletions

View File

@ -518,6 +518,37 @@ epsilon and negative checks everywhere in kinematics, but why? Should research
it more, but I think the better approach is to use fixed-point arithmetic for it more, but I think the better approach is to use fixed-point arithmetic for
everything (aka u8 or whatever). everything (aka u8 or whatever).
Problems with floats:
- they dont natively order
- they arent PartialEq
- serialization sometimes breaks
- epsilon comparison issues
Options:
- just to solve epsilon comparison issues
- https://crates.io/crates/float-cmp
- https://crates.io/crates/approx
- just to get Ord and Eq
- https://crates.io/crates/decorum
- https://crates.io/crates/ordered-float
- use rational / fraction types
- https://crates.io/crates/fraction
- https://crates.io/crates/rug
- this seems a bit overpowered
- use my own custom wrapper type around u8 or whatever size makes sense for each thing
- representing 0.1s or 0.1m or whatever
- use a fixed point arithmetic crate
- https://crates.io/crates/fpa
- https://crates.io/crates/fixed
- https://crates.io/crates/fix
- would want to wrap the types anyway; only some operations make sense
- can we compare results with the prev float approach? make them store the
other thing, compare results? or compare the results of a sim?
- is it possible to do this change gradually? unlikely...
- moment in time (tick) - moment in time (tick)
- resolution: 0.1s with u32, so about 13.5 years - resolution: 0.1s with u32, so about 13.5 years
- duration - duration
@ -822,3 +853,10 @@ It happens because a car was previously throttling itself due to somebody in
the way, but as soon as they start a turn, the car eagerly jumps ahead. the way, but as soon as they start a turn, the car eagerly jumps ahead.
ah no, it's because we use max_lookahead_dist in accel_to_follow, and the speed limit we assert is the old road's speed. ah no, it's because we use max_lookahead_dist in accel_to_follow, and the speed limit we assert is the old road's speed.
## Moving away from piston
- options
- gfx (pre-II or not?) + winit
- https://suhr.github.io/gsgt/
- glium (unmaintained)

View File

@ -71,4 +71,5 @@ fn main() {
} }
}), }),
); );
sim::save_backtraces("call_graph.json");
} }

View File

@ -1,20 +1,16 @@
use abstutil;
use backtrace::Backtrace; use backtrace::Backtrace;
use std::collections::HashMap; use std::collections::HashSet;
use std::sync::Mutex; use std::sync::Mutex;
#[derive(Debug)]
struct CallStack {
calls: Vec<String>,
}
lazy_static! { lazy_static! {
static ref BACKTRACES: Mutex<HashMap<String, CallStack>> = Mutex::new(HashMap::new()); static ref BACKTRACES: Mutex<HashSet<Vec<String>>> = Mutex::new(HashSet::new());
} }
pub fn capture_backtrace() { pub fn capture_backtrace(event: &str) {
let bt = Backtrace::new(); let bt = Backtrace::new();
let mut found_this_fxn = false; let mut found_this_fxn = false;
let mut calls: Vec<String> = Vec::new(); let mut calls: Vec<String> = vec![event.to_string()];
for f in bt.frames() { for f in bt.frames() {
let raw_name = format!("{}", f.symbols()[0].name().unwrap()); let raw_name = format!("{}", f.symbols()[0].name().unwrap());
let mut raw_name_parts: Vec<&str> = raw_name.split("::").collect(); let mut raw_name_parts: Vec<&str> = raw_name.split("::").collect();
@ -33,15 +29,14 @@ pub fn capture_backtrace() {
} }
} }
let caller = &calls[0]; BACKTRACES.lock().unwrap().insert(calls);
let stack = CallStack {
calls: calls[1..].to_vec(),
};
println!("insert {}: {:?}", caller, stack);
let mut remember = BACKTRACES.lock().unwrap();
remember.insert(caller.to_string(), stack);
} }
// TODO dump to file pub fn save_backtraces(path: &str) {
// TODO manually call when events are created and at other interesting points abstutil::write_json(path, &(*BACKTRACES.lock().unwrap())).unwrap();
// TODO compiler flag so capture_backtrace is usually a no-op }
// TODO call from all interesting methods in a few different types; maybe use macros to help
// TODO compiler flag so capture_backtrace is usually a no-op. actually, looks like this doesn't
// work in --release mode, so use that.
// TODO script to organize and visualize results

View File

@ -48,6 +48,7 @@ use dimensioned::si;
pub use events::Event; pub use events::Event;
use geom::{Angle, Pt2D}; use geom::{Angle, Pt2D};
pub use helpers::load; pub use helpers::load;
pub use instrument::save_backtraces;
use map_model::{LaneID, Map, TurnID}; use map_model::{LaneID, Map, TurnID};
pub use sim::{Benchmark, Sim}; pub use sim::{Benchmark, Sim};
use std::fmt; use std::fmt;

View File

@ -7,6 +7,7 @@ use draw_car::DrawCar;
use draw_ped::DrawPedestrian; use draw_ped::DrawPedestrian;
use driving::DrivingSimState; use driving::DrivingSimState;
use failure::Error; use failure::Error;
use instrument::capture_backtrace;
use intersections::IntersectionSimState; use intersections::IntersectionSimState;
use kinematics::Vehicle; use kinematics::Vehicle;
use map_model::{IntersectionID, LaneID, LaneType, Map, Turn, TurnID}; use map_model::{IntersectionID, LaneID, LaneType, Map, Turn, TurnID};
@ -169,6 +170,7 @@ impl Sim {
&self.car_properties, &self.car_properties,
)? { )? {
events.push(Event::CarReachedParkingSpot(p.clone())); events.push(Event::CarReachedParkingSpot(p.clone()));
capture_backtrace("CarReachedParkingSpot");
self.parking_state.add_parked_car(p.clone()); self.parking_state.add_parked_car(p.clone());
self.spawner.car_reached_parking_spot( self.spawner.car_reached_parking_spot(
self.time, self.time,
@ -185,6 +187,7 @@ impl Sim {
.step(&mut events, TIMESTEP, map, &mut self.intersection_state)? .step(&mut events, TIMESTEP, map, &mut self.intersection_state)?
{ {
events.push(Event::PedReachedParkingSpot(ped, spot)); events.push(Event::PedReachedParkingSpot(ped, spot));
capture_backtrace("PedReachedParkingSpot");
self.spawner.ped_reached_parking_spot( self.spawner.ped_reached_parking_spot(
self.time, self.time,
ped, ped,

View File

@ -138,7 +138,7 @@ impl TransitSimState {
self.buses.get_mut(&car).unwrap().state = self.buses.get_mut(&car).unwrap().state =
BusState::AtStop(stop_idx, time + 10.0 * si::S); BusState::AtStop(stop_idx, time + 10.0 * si::S);
events.push(Event::BusArrivedAtStop(car, stop.id)); events.push(Event::BusArrivedAtStop(car, stop.id));
capture_backtrace(); capture_backtrace("BusArrivedAtStop");
if view.debug { if view.debug {
println!("{} arrived at stop {:?}, now waiting", car, stop); println!("{} arrived at stop {:?}, now waiting", car, stop);
} }
@ -156,6 +156,7 @@ impl TransitSimState {
let next_stop = route.next_stop(stop_idx); let next_stop = route.next_stop(stop_idx);
self.buses.get_mut(&car).unwrap().state = BusState::DrivingToStop(next_stop); self.buses.get_mut(&car).unwrap().state = BusState::DrivingToStop(next_stop);
events.push(Event::BusDepartedFromStop(car, stop.id)); events.push(Event::BusDepartedFromStop(car, stop.id));
capture_backtrace("BusDepartedFromStop");
if view.debug { if view.debug {
println!("{} departing from stop {:?}", car, stop); println!("{} departing from stop {:?}", car, stop);
} }
@ -210,6 +211,7 @@ impl TransitSimState {
for p in walking_sim.get_peds_waiting_at_stop(stop.id).into_iter() { for p in walking_sim.get_peds_waiting_at_stop(stop.id).into_iter() {
if trips.should_ped_board_bus(p, b.route) { if trips.should_ped_board_bus(p, b.route) {
events.push(Event::PedEntersBus(p, b.car)); events.push(Event::PedEntersBus(p, b.car));
capture_backtrace("PedEntersBus");
b.passengers.push(p); b.passengers.push(p);
walking_sim.ped_joined_bus(p, stop.id); walking_sim.ped_joined_bus(p, stop.id);
} }
@ -226,6 +228,7 @@ impl TransitSimState {
b.passengers.retain(|p| { b.passengers.retain(|p| {
if trips.should_ped_leave_bus(*p, stop.id) { if trips.should_ped_leave_bus(*p, stop.id) {
events.push(Event::PedLeavesBus(*p, car)); events.push(Event::PedLeavesBus(*p, car));
capture_backtrace("PedLeavesBus");
// TODO would be a little cleaner to return this info up to sim and have it // TODO would be a little cleaner to return this info up to sim and have it
// plumb through to spawner? not sure // plumb through to spawner? not sure
spawner.ped_finished_bus_ride(now, *p, stop.id, trips, map); spawner.ped_finished_bus_ride(now, *p, stop.id, trips, map);

View File

@ -4,6 +4,7 @@ use dimensioned::si;
use draw_ped::DrawPedestrian; use draw_ped::DrawPedestrian;
use failure::Error; use failure::Error;
use geom::{Line, Pt2D}; use geom::{Line, Pt2D};
use instrument::capture_backtrace;
use intersections::{IntersectionSimState, Request}; use intersections::{IntersectionSimState, Request};
use map_model::{BuildingID, BusStop, IntersectionID, Lane, LaneID, Map, Turn, TurnID}; use map_model::{BuildingID, BusStop, IntersectionID, Lane, LaneID, Map, Turn, TurnID};
use multimap::MultiMap; use multimap::MultiMap;
@ -216,6 +217,7 @@ impl Pedestrian {
fp.dist_along -= new_dist; fp.dist_along -= new_dist;
if fp.dist_along < 0.0 * si::M { if fp.dist_along < 0.0 * si::M {
events.push(Event::PedReachedBuilding(self.id, fp.bldg)); events.push(Event::PedReachedBuilding(self.id, fp.bldg));
capture_backtrace("PedReachedBuilding");
return true; return true;
} }
false false
@ -399,6 +401,7 @@ impl WalkingSimState {
Action::WaitAtBusStop(stop) => { Action::WaitAtBusStop(stop) => {
self.peds.get_mut(&id).unwrap().active = false; self.peds.get_mut(&id).unwrap().active = false;
events.push(Event::PedReachedBusStop(*id, stop)); events.push(Event::PedReachedBusStop(*id, stop));
capture_backtrace("PedReachedBusStop");
self.peds_per_bus_stop.insert(stop, *id); self.peds_per_bus_stop.insert(stop, *id);
} }
Action::StartParkedCar(ref spot) => { Action::StartParkedCar(ref spot) => {