(
self,
thread_id: int,
start_ms: int | None = None,
end_ms: int | None = None,
metric: str = "net",
)
| 976 | return self._stack_tree_to_text(self.stack_tree(thread_id, start_ms=start_ms, end_ms=end_ms, metric=metric)) |
| 977 | |
| 978 | def stack_tree( |
| 979 | self, |
| 980 | thread_id: int, |
| 981 | start_ms: int | None = None, |
| 982 | end_ms: int | None = None, |
| 983 | metric: str = "net", |
| 984 | ) -> dict[str, Any]: |
| 985 | metric = _normalize_metric_name(metric) |
| 986 | start_tick, end_tick = self._normalize_window(start_ms, end_ms) |
| 987 | tree: dict[str, Any] = { |
| 988 | "thread_id": thread_id, |
| 989 | "function_id": None, |
| 990 | "display_name": f"Thread {thread_id}", |
| 991 | "canonical_name": f"Thread {thread_id}", |
| 992 | "malloc": 0.0, |
| 993 | "free": 0.0, |
| 994 | "children": {}, |
| 995 | } |
| 996 | |
| 997 | for _tick_ms, current_thread_id, leaf_node_id, malloc_bytes, free_bytes in self._iter_records( |
| 998 | start_tick, end_tick, (thread_id,) |
| 999 | ): |
| 1000 | if current_thread_id != thread_id: |
| 1001 | continue |
| 1002 | node = tree |
| 1003 | node["malloc"] += float(malloc_bytes) |
| 1004 | node["free"] += float(free_bytes) |
| 1005 | for function_id in self.reader.node_paths[leaf_node_id]: |
| 1006 | child = node["children"].setdefault(function_id, self._new_stack_tree_node(function_id)) |
| 1007 | child["malloc"] += float(malloc_bytes) |
| 1008 | child["free"] += float(free_bytes) |
| 1009 | node = child |
| 1010 | |
| 1011 | return self._apply_stack_tree_shares(self._finalize_stack_tree(tree, metric)) |
| 1012 | |
| 1013 | def export_json(self, output: str | Path) -> Path: |
| 1014 | output_path = Path(output) |
no test coverage detected