| 176 | } |
| 177 | |
| 178 | fn write_recursively<W: io::Write>( |
| 179 | out: &mut W, |
| 180 | sorted_scopes: &[(ScopeId, Scope)], |
| 181 | current: &(ScopeId, Scope), |
| 182 | parent_duration: Option<Duration>, |
| 183 | depth: usize, |
| 184 | is_parallel: bool, |
| 185 | ) -> io::Result<()> { |
| 186 | let (id, scope) = current; |
| 187 | |
| 188 | for _ in 0..depth { |
| 189 | write!(out, " ")?; |
| 190 | } |
| 191 | |
| 192 | let duration_sum_secs = scope.duration_sum.as_secs_f64(); |
| 193 | let parent_duration_secs = parent_duration.map_or(duration_sum_secs, |t| t.as_secs_f64()); |
| 194 | let percent = duration_sum_secs / parent_duration_secs * 100.0; |
| 195 | |
| 196 | writeln!( |
| 197 | out, |
| 198 | "{}: {}{:3.2}%, {:>4.2}ms avg, {} {} (total: {:.3}s)", |
| 199 | scope.name, |
| 200 | if is_parallel { "≈" } else { "" }, |
| 201 | percent, |
| 202 | duration_sum_secs * 1000.0 / (scope.num_calls as f64), |
| 203 | scope.num_calls, |
| 204 | if scope.num_calls > 1 { "calls" } else { "call" }, |
| 205 | duration_sum_secs |
| 206 | )?; |
| 207 | |
| 208 | // Compute sum of runtimes of children |
| 209 | let mut children_runtime = Duration::default(); |
| 210 | let current_hash = ScopeId::get_hash(Some(id)); |
| 211 | for s in sorted_scopes { |
| 212 | let (child_id, child_scope) = s; |
| 213 | if child_id.parent_hash == current_hash { |
| 214 | children_runtime += child_scope.duration_sum; |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | // If children were run in parallel, their total runtime can be larger than that of the current scope |
| 219 | let children_parallel = children_runtime > scope.duration_sum; |
| 220 | let own_runtime = if children_parallel { |
| 221 | children_runtime |
| 222 | } else { |
| 223 | scope.duration_sum |
| 224 | }; |
| 225 | |
| 226 | // Process children in sorted order |
| 227 | let current_hash = ScopeId::get_hash(Some(id)); |
| 228 | for s in sorted_scopes { |
| 229 | let (child_id, _) = s; |
| 230 | if child_id.parent_hash == current_hash { |
| 231 | // TODO: Prevent infinite recursion for recursive functions, maybe remove current scope from map? |
| 232 | // Maybe we don't have this problem, instead it will be a huge chain which is as long as the recursion depth... |
| 233 | write_recursively( |
| 234 | out, |
| 235 | sorted_scopes, |