Insert a trace into the flame graph.
(&mut self, trace: &[ArchivedFrame], weight: u64, inline_frames: bool)
| 849 | |
| 850 | /// Insert a trace into the flame graph. |
| 851 | pub fn insert_trace(&mut self, trace: &[ArchivedFrame], weight: u64, inline_frames: bool) { |
| 852 | let mut node = self; |
| 853 | node.weight += weight; |
| 854 | |
| 855 | for frame in trace.iter().rev() { |
| 856 | let frame: Frame = (*frame).into(); |
| 857 | |
| 858 | // WARN: this `find` makes flame graph construction O(n^2) in the |
| 859 | // worst case, but I found that in the average case this is |
| 860 | // actually quite a bit faster than a hashmap/btreemap based |
| 861 | // approach. Most nodes only have one or two nodes. |
| 862 | // TODO: experiment with a mixed approach that uses linear search for |
| 863 | // nodes with <8 nodes and a hashmap for larger ones |
| 864 | if let Some(mut child) = node.children.iter_mut().find(|x| x.id == frame.id.into()) { |
| 865 | child.weight += weight; |
| 866 | |
| 867 | for _ in 0..child.inline_skip { |
| 868 | child = child.children.first_mut().unwrap(); |
| 869 | child.weight += weight; |
| 870 | } |
| 871 | |
| 872 | node = unsafe { &mut *(child as *mut _) }; |
| 873 | continue; |
| 874 | } |
| 875 | |
| 876 | if let FrameKind::Abort = frame.kind { |
| 877 | node.children.push(FlameGraphNode { |
| 878 | weight, |
| 879 | fg_color: Color32::BLACK, |
| 880 | bg_color: frame_kind_color(frame.kind), |
| 881 | id: frame.id, |
| 882 | text: match error_spec_by_id(frame.id.addr_or_line) { |
| 883 | Some(spec) => { |
| 884 | format!("<unwinding aborted: {}>", spec.name) |
| 885 | } |
| 886 | None => { |
| 887 | format!("<unwinding aborted: error code {}>", frame.id.addr_or_line) |
| 888 | } |
| 889 | }, |
| 890 | inline_skip: 0, |
| 891 | children: vec![], |
| 892 | }); |
| 893 | node = node.children.last_mut().unwrap(); |
| 894 | continue; |
| 895 | } |
| 896 | |
| 897 | let inline_frames = symbolize_frame(frame, inline_frames); |
| 898 | assert!(!inline_frames.is_empty()); |
| 899 | let mut inline_len = Some((inline_frames.len() - 1) as u16); |
| 900 | |
| 901 | for (i, inline_node) in inline_frames.into_iter().enumerate() { |
| 902 | assert!(i == 0 || node.children.is_empty()); |
| 903 | |
| 904 | node.children.push(FlameGraphNode { |
| 905 | weight, |
| 906 | fg_color: Color32::BLACK, |
| 907 | bg_color: frame_kind_color(frame.kind), |
| 908 | id: inline_node.raw.id, |
no test coverage detected