viztracer 1.0.4__cp310-cp310-win_amd64.whl → 1.1.0__cp310-cp310-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of viztracer might be problematic. Click here for more details.
- viztracer/__init__.py +1 -1
- viztracer/code_monkey.py +10 -13
- viztracer/decorator.py +9 -12
- viztracer/event_base.py +2 -2
- viztracer/functree.py +7 -7
- viztracer/main.py +9 -13
- viztracer/modules/snaptrace.c +14 -12
- viztracer/modules/util.c +1 -5
- viztracer/modules/vcompressor/vc_dump.c +4 -24
- viztracer/modules/vcompressor/vcompressor.c +13 -13
- viztracer/patch.py +10 -6
- viztracer/report_builder.py +8 -8
- viztracer/snaptrace.cp310-win_amd64.pyd +0 -0
- viztracer/snaptrace.pyi +8 -8
- viztracer/util.py +1 -2
- viztracer/vcompressor.cp310-win_amd64.pyd +0 -0
- viztracer/viewer.py +5 -5
- viztracer/vizlogging.py +1 -2
- viztracer/vizplugin.py +3 -3
- viztracer/viztracer.py +16 -16
- viztracer/web_dist/index.html +1 -1
- viztracer/web_dist/service_worker.js +103 -1
- viztracer/web_dist/trace_processor +32 -31
- viztracer/web_dist/v52.0-6b9586def/assets/MaterialSymbolsOutlined.woff2 +0 -0
- viztracer/web_dist/v52.0-6b9586def/engine_bundle.js +3 -0
- viztracer/web_dist/v52.0-6b9586def/frontend_bundle.js +5495 -0
- viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/manifest.json +10 -8
- viztracer/web_dist/v52.0-6b9586def/perfetto.css +5737 -0
- viztracer/web_dist/v52.0-6b9586def/stdlib_docs.json +1 -0
- viztracer/web_dist/v52.0-6b9586def/trace_config_utils.wasm +0 -0
- viztracer/web_dist/{v47.0-02b2414d5/traceconv.wasm → v52.0-6b9586def/trace_processor.wasm} +0 -0
- viztracer/web_dist/v52.0-6b9586def/trace_processor_memory64.wasm +0 -0
- viztracer/web_dist/{v47.0-02b2414d5/trace_processor.wasm → v52.0-6b9586def/traceconv.wasm} +0 -0
- viztracer/web_dist/v52.0-6b9586def/traceconv_bundle.js +2 -0
- viztracer-1.1.0.dist-info/METADATA +316 -0
- viztracer-1.1.0.dist-info/RECORD +109 -0
- {viztracer-1.0.4.dist-info → viztracer-1.1.0.dist-info}/WHEEL +1 -1
- viztracer/web_dist/v47.0-02b2414d5/assets/._MaterialSymbolsOutlined.woff2 +0 -0
- viztracer/web_dist/v47.0-02b2414d5/assets/MaterialSymbolsOutlined.woff2 +0 -0
- viztracer/web_dist/v47.0-02b2414d5/engine_bundle.js +0 -3
- viztracer/web_dist/v47.0-02b2414d5/frontend_bundle.js +0 -4994
- viztracer/web_dist/v47.0-02b2414d5/perfetto.css +0 -5133
- viztracer/web_dist/v47.0-02b2414d5/traceconv_bundle.js +0 -2
- viztracer-1.0.4.dist-info/METADATA +0 -537
- viztracer-1.0.4.dist-info/RECORD +0 -107
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/Roboto-100.woff2 +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/Roboto-300.woff2 +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/Roboto-400.woff2 +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/Roboto-500.woff2 +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/RobotoCondensed-Light.woff2 +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/RobotoCondensed-Regular.woff2 +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/RobotoMono-Regular.woff2 +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/brand.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/catapult_trace_viewer.html +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/catapult_trace_viewer.js +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/favicon.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/logo-128.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/logo-3d.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_atrace.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_battery_counters.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_board_voltage.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_cpu_coarse.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_cpu_fine.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_cpu_freq.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_cpu_voltage.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_frame_timeline.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_ftrace.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_gpu_mem_total.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_java_heap_dump.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_lmk.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_logcat.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_long_trace.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_mem_hifreq.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_meminfo.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_native_heap_profiler.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_one_shot.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_profiling.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_ps_stats.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_ring_buf.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_syscalls.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_vmstat.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/scheduling_latency.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/vscode-icon.png +0 -0
- /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/index.html +0 -0
- {viztracer-1.0.4.dist-info → viztracer-1.1.0.dist-info}/entry_points.txt +0 -0
- {viztracer-1.0.4.dist-info → viztracer-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {viztracer-1.0.4.dist-info → viztracer-1.1.0.dist-info}/licenses/NOTICE.txt +0 -0
- {viztracer-1.0.4.dist-info → viztracer-1.1.0.dist-info}/top_level.txt +0 -0
viztracer/__init__.py
CHANGED
viztracer/code_monkey.py
CHANGED
|
@@ -5,7 +5,7 @@ import ast
|
|
|
5
5
|
import copy
|
|
6
6
|
import re
|
|
7
7
|
from functools import reduce
|
|
8
|
-
from typing import Any, Callable
|
|
8
|
+
from typing import Any, Callable
|
|
9
9
|
|
|
10
10
|
from .util import color_print
|
|
11
11
|
|
|
@@ -18,13 +18,13 @@ class AstTransformer(ast.NodeTransformer):
|
|
|
18
18
|
self.curr_lineno: int = 0
|
|
19
19
|
self.log_func_exec_enable: bool = False
|
|
20
20
|
|
|
21
|
-
def visit_Assign(self, node: ast.Assign) ->
|
|
21
|
+
def visit_Assign(self, node: ast.Assign) -> ast.stmt | list[ast.stmt]:
|
|
22
22
|
return self._visit_generic_assign(node)
|
|
23
23
|
|
|
24
|
-
def visit_AugAssign(self, node: ast.AugAssign) ->
|
|
24
|
+
def visit_AugAssign(self, node: ast.AugAssign) -> ast.stmt | list[ast.stmt]:
|
|
25
25
|
return self._visit_generic_assign(node)
|
|
26
26
|
|
|
27
|
-
def visit_AnnAssign(self, node: ast.AnnAssign) ->
|
|
27
|
+
def visit_AnnAssign(self, node: ast.AnnAssign) -> ast.stmt | list[ast.stmt]:
|
|
28
28
|
return self._visit_generic_assign(node)
|
|
29
29
|
|
|
30
30
|
def visit_FunctionDef(self, node: ast.FunctionDef) -> ast.FunctionDef:
|
|
@@ -69,13 +69,13 @@ class AstTransformer(ast.NodeTransformer):
|
|
|
69
69
|
node.body = instrumented_nodes + node.body
|
|
70
70
|
return node
|
|
71
71
|
|
|
72
|
-
def visit_Raise(self, node: ast.Raise) ->
|
|
72
|
+
def visit_Raise(self, node: ast.Raise) -> ast.AST | list[ast.AST]:
|
|
73
73
|
if self.inst_type == "log_exception":
|
|
74
74
|
instrument_node = self.get_instrument_node_by_node("Exception", node.exc)
|
|
75
75
|
return [instrument_node, node]
|
|
76
76
|
return node
|
|
77
77
|
|
|
78
|
-
def _visit_generic_assign(self, node:
|
|
78
|
+
def _visit_generic_assign(self, node: ast.Assign | ast.AugAssign | ast.AnnAssign) -> list[ast.stmt]:
|
|
79
79
|
self.generic_visit(node)
|
|
80
80
|
ret: list[ast.stmt] = [node]
|
|
81
81
|
self.curr_lineno = node.lineno
|
|
@@ -174,7 +174,7 @@ class AstTransformer(ast.NodeTransformer):
|
|
|
174
174
|
else:
|
|
175
175
|
raise ValueError(f"{name} is not supported")
|
|
176
176
|
|
|
177
|
-
def get_instrument_node_by_node(self, trigger: str, node:
|
|
177
|
+
def get_instrument_node_by_node(self, trigger: str, node: ast.expr | None) -> ast.Expr:
|
|
178
178
|
var_node: ast.expr
|
|
179
179
|
if node is None:
|
|
180
180
|
name = f"{trigger}"
|
|
@@ -235,17 +235,14 @@ class AstTransformer(ast.NodeTransformer):
|
|
|
235
235
|
n.ctx = ast.Load() # type: ignore
|
|
236
236
|
return new_node
|
|
237
237
|
|
|
238
|
-
def get_string_of_expr(self, node:
|
|
238
|
+
def get_string_of_expr(self, node: ast.expr | ast.slice) -> str:
|
|
239
239
|
"""
|
|
240
240
|
Try to do "unparse" of the node
|
|
241
241
|
"""
|
|
242
242
|
if isinstance(node, ast.Name):
|
|
243
243
|
return node.id
|
|
244
244
|
elif isinstance(node, ast.Constant):
|
|
245
|
-
|
|
246
|
-
return f"'{node.value}'"
|
|
247
|
-
else:
|
|
248
|
-
return f"{node.value}"
|
|
245
|
+
return repr(node.value)
|
|
249
246
|
elif isinstance(node, ast.Attribute):
|
|
250
247
|
return f"{self.get_string_of_expr(node.value)}.{node.attr}"
|
|
251
248
|
elif isinstance(node, ast.Subscript):
|
|
@@ -333,7 +330,7 @@ class CodeMonkey:
|
|
|
333
330
|
def __init__(self, file_name: str) -> None:
|
|
334
331
|
self.file_name: str = file_name
|
|
335
332
|
self._compile: Callable = compile
|
|
336
|
-
self.source_processor:
|
|
333
|
+
self.source_processor: SourceProcessor | None = None
|
|
337
334
|
self.ast_transformers: list[AstTransformer] = []
|
|
338
335
|
|
|
339
336
|
def add_instrument(self, inst_type: str, inst_args: dict[str, dict]) -> None:
|
viztracer/decorator.py
CHANGED
|
@@ -5,7 +5,7 @@ import functools
|
|
|
5
5
|
import multiprocessing
|
|
6
6
|
import os
|
|
7
7
|
import time
|
|
8
|
-
from typing import Any, Callable,
|
|
8
|
+
from typing import Any, Callable, TypeVar, overload
|
|
9
9
|
|
|
10
10
|
from .viztracer import VizTracer, get_tracer
|
|
11
11
|
|
|
@@ -15,19 +15,18 @@ R = TypeVar("R")
|
|
|
15
15
|
|
|
16
16
|
@overload
|
|
17
17
|
def ignore_function(method: None,
|
|
18
|
-
tracer:
|
|
18
|
+
tracer: VizTracer | None = None) -> Callable[[Callable[..., R]], Callable[..., R]]:
|
|
19
19
|
pass # pragma: no cover
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
@overload
|
|
23
23
|
def ignore_function(method: Callable[..., R],
|
|
24
|
-
tracer:
|
|
24
|
+
tracer: VizTracer | None = None) -> Callable[..., R]:
|
|
25
25
|
pass # pragma: no cover
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
def ignore_function(method:
|
|
29
|
-
tracer:
|
|
30
|
-
Callable[[Callable[..., R]], Callable[..., R]]]:
|
|
28
|
+
def ignore_function(method: Callable[..., R] | None = None,
|
|
29
|
+
tracer: VizTracer | None = None) -> Callable[..., R] | Callable[[Callable[..., R]], Callable[..., R]]:
|
|
31
30
|
|
|
32
31
|
def inner(func: Callable[..., R]) -> Callable[..., R]:
|
|
33
32
|
|
|
@@ -65,10 +64,9 @@ def trace_and_save(method: Callable[..., R],
|
|
|
65
64
|
pass # pragma: no cover
|
|
66
65
|
|
|
67
66
|
|
|
68
|
-
def trace_and_save(method:
|
|
67
|
+
def trace_and_save(method: Callable[..., R] | None = None,
|
|
69
68
|
output_dir: str = "./",
|
|
70
|
-
**viztracer_kwargs) ->
|
|
71
|
-
Callable[[Callable[..., R]], Callable[..., R]]]:
|
|
69
|
+
**viztracer_kwargs) -> Callable[..., R] | Callable[[Callable[..., R]], Callable[..., R]]:
|
|
72
70
|
|
|
73
71
|
def inner(func: Callable[..., R]) -> Callable[..., R]:
|
|
74
72
|
|
|
@@ -158,10 +156,9 @@ def log_sparse(func: Callable[..., R],
|
|
|
158
156
|
pass # pragma: no cover
|
|
159
157
|
|
|
160
158
|
|
|
161
|
-
def log_sparse(func:
|
|
159
|
+
def log_sparse(func: Callable[..., R] | None = None,
|
|
162
160
|
stack_depth: int = 0,
|
|
163
|
-
dynamic_tracer_check: bool = False) ->
|
|
164
|
-
Callable[[Callable[..., R]], Callable[..., R]]]:
|
|
161
|
+
dynamic_tracer_check: bool = False) -> Callable[..., R] | Callable[[Callable[..., R]], Callable[..., R]]:
|
|
165
162
|
if func is None:
|
|
166
163
|
return functools.partial(_log_sparse_wrapper, stack_depth=stack_depth, dynamic_tracer_check=dynamic_tracer_check)
|
|
167
164
|
return _log_sparse_wrapper(func=func, stack_depth=stack_depth, dynamic_tracer_check=dynamic_tracer_check)
|
viztracer/event_base.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# For details: https://github.com/gaogaotiantian/viztracer/blob/master/NOTICE.txt
|
|
3
3
|
|
|
4
4
|
import functools
|
|
5
|
-
from typing import Any, Callable, Literal
|
|
5
|
+
from typing import Any, Callable, Literal
|
|
6
6
|
|
|
7
7
|
from .viztracer import VizTracer
|
|
8
8
|
|
|
@@ -59,7 +59,7 @@ class _EventBase:
|
|
|
59
59
|
self._viztracer_log()
|
|
60
60
|
|
|
61
61
|
@staticmethod
|
|
62
|
-
def triggerlog(method:
|
|
62
|
+
def triggerlog(method: Callable | None = None,
|
|
63
63
|
when: Literal["after", "before", "both"] = "after") -> Callable:
|
|
64
64
|
if when not in ["after", "before", "both"]:
|
|
65
65
|
raise ValueError(f"when has to be one of 'after', 'before' or 'both', not {when}")
|
viztracer/functree.py
CHANGED
|
@@ -4,18 +4,18 @@
|
|
|
4
4
|
import bisect
|
|
5
5
|
import copy
|
|
6
6
|
import re
|
|
7
|
-
from typing import Any, Generator
|
|
7
|
+
from typing import Any, Generator
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class FuncTreeNode:
|
|
11
11
|
name_regex = r"(.*) \((.*?):([0-9]+)\)"
|
|
12
12
|
|
|
13
|
-
def __init__(self, event:
|
|
14
|
-
self.filename:
|
|
15
|
-
self.lineno:
|
|
16
|
-
self.is_python:
|
|
17
|
-
self.funcname:
|
|
18
|
-
self.parent:
|
|
13
|
+
def __init__(self, event: dict[str, Any] | None = None) -> None:
|
|
14
|
+
self.filename: str | None = None
|
|
15
|
+
self.lineno: int | None = None
|
|
16
|
+
self.is_python: bool | None = False
|
|
17
|
+
self.funcname: str | None = None
|
|
18
|
+
self.parent: FuncTreeNode | None = None
|
|
19
19
|
self.children: list[FuncTreeNode] = []
|
|
20
20
|
self.start: float = - (2 ** 64)
|
|
21
21
|
self.end: float = 2 ** 64
|
viztracer/main.py
CHANGED
|
@@ -19,7 +19,7 @@ import time
|
|
|
19
19
|
import types
|
|
20
20
|
import re
|
|
21
21
|
from types import CodeType
|
|
22
|
-
from typing import Any
|
|
22
|
+
from typing import Any
|
|
23
23
|
|
|
24
24
|
from . import __version__
|
|
25
25
|
from .code_monkey import CodeMonkey
|
|
@@ -31,12 +31,12 @@ from .viztracer import VizTracer
|
|
|
31
31
|
# For all the procedures in VizUI, return a tuple as the result
|
|
32
32
|
# The first element bool indicates whether the procedure succeeds
|
|
33
33
|
# The second element is the error message if it fails.
|
|
34
|
-
VizProcedureResult = tuple[bool,
|
|
34
|
+
VizProcedureResult = tuple[bool, str | None]
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
class VizUI:
|
|
38
38
|
def __init__(self) -> None:
|
|
39
|
-
self.tracer:
|
|
39
|
+
self.tracer: VizTracer | None = None
|
|
40
40
|
self.parser: argparse.ArgumentParser = self.create_parser()
|
|
41
41
|
self.verbose: int = 1
|
|
42
42
|
self.ofile: str = "result.json"
|
|
@@ -199,7 +199,7 @@ class VizUI:
|
|
|
199
199
|
def parse(self, argv: list[str]) -> VizProcedureResult:
|
|
200
200
|
# If -- or --run exists, all the commands after --/--run are the commands we need to run
|
|
201
201
|
# We need to filter those out, they might conflict with our arguments
|
|
202
|
-
idx:
|
|
202
|
+
idx: int | None = None
|
|
203
203
|
if "--" in argv[1:]:
|
|
204
204
|
idx = argv.index("--")
|
|
205
205
|
elif "--run" in argv[1:]:
|
|
@@ -295,7 +295,7 @@ class VizUI:
|
|
|
295
295
|
|
|
296
296
|
return True, None
|
|
297
297
|
|
|
298
|
-
def search_file(self, file_name: str) ->
|
|
298
|
+
def search_file(self, file_name: str) -> str | None:
|
|
299
299
|
if os.path.isfile(file_name):
|
|
300
300
|
return file_name
|
|
301
301
|
|
|
@@ -326,7 +326,7 @@ class VizUI:
|
|
|
326
326
|
return self.uninstall()
|
|
327
327
|
elif self.options.cmd_string is not None:
|
|
328
328
|
return self.run_string()
|
|
329
|
-
elif self.options.module:
|
|
329
|
+
elif self.options.module is not None:
|
|
330
330
|
return self.run_module()
|
|
331
331
|
elif self.command:
|
|
332
332
|
return self.run_command()
|
|
@@ -342,7 +342,7 @@ class VizUI:
|
|
|
342
342
|
self.parser.print_help()
|
|
343
343
|
return True, None
|
|
344
344
|
|
|
345
|
-
def run_code(self, code:
|
|
345
|
+
def run_code(self, code: CodeType | str, global_dict: dict[str, Any]) -> VizProcedureResult:
|
|
346
346
|
options = self.options
|
|
347
347
|
self.parent_pid = os.getpid()
|
|
348
348
|
|
|
@@ -386,16 +386,12 @@ class VizUI:
|
|
|
386
386
|
if not options.log_exit:
|
|
387
387
|
tracer.stop(stop_option="flush_as_finish")
|
|
388
388
|
|
|
389
|
-
# Clear to global_dict to release all references.
|
|
390
|
-
# This is helpful for some deadlock issues.
|
|
391
|
-
global_dict.clear()
|
|
392
|
-
|
|
393
389
|
# issue141 - concurrent.future requires a proper release by executing
|
|
394
390
|
# threading._threading_atexits or it will deadlock if not explicitly
|
|
395
391
|
# release the resource in the code
|
|
396
392
|
# Python 3.9+ has this issue
|
|
397
393
|
if threading._threading_atexits: # type: ignore
|
|
398
|
-
for atexit_call in threading._threading_atexits: # type: ignore
|
|
394
|
+
for atexit_call in reversed(threading._threading_atexits): # type: ignore
|
|
399
395
|
atexit_call()
|
|
400
396
|
threading._threading_atexits = [] # type: ignore
|
|
401
397
|
|
|
@@ -526,7 +522,7 @@ class VizUI:
|
|
|
526
522
|
print(__version__)
|
|
527
523
|
return True, None
|
|
528
524
|
|
|
529
|
-
def _check_attach_availability(self) -> tuple[bool,
|
|
525
|
+
def _check_attach_availability(self) -> tuple[bool, str | None]:
|
|
530
526
|
if sys.platform == "win32":
|
|
531
527
|
return False, "VizTracer does not support this feature on Windows"
|
|
532
528
|
|
viztracer/modules/snaptrace.c
CHANGED
|
@@ -164,9 +164,11 @@ verbose_printf(TracerObject* self, int v, const char* fmt, ...)
|
|
|
164
164
|
void
|
|
165
165
|
clear_stack(struct FunctionNode** stack_top) {
|
|
166
166
|
Py_CLEAR((*stack_top)->args);
|
|
167
|
+
Py_CLEAR((*stack_top)->func);
|
|
167
168
|
while ((*stack_top)->prev) {
|
|
168
169
|
(*stack_top) = (*stack_top) -> prev;
|
|
169
170
|
Py_CLEAR((*stack_top)->args);
|
|
171
|
+
Py_CLEAR((*stack_top)->func);
|
|
170
172
|
}
|
|
171
173
|
}
|
|
172
174
|
|
|
@@ -419,7 +421,7 @@ tracer_pycall_callback(TracerObject* self, PyCodeObject* code)
|
|
|
419
421
|
info->paused = 1;
|
|
420
422
|
for (size_t i = 0; i < sizeof(curr_task_getters)/sizeof(curr_task_getters[0]); i++) {
|
|
421
423
|
if (curr_task_getters[i] != NULL) {
|
|
422
|
-
curr_task =
|
|
424
|
+
curr_task = PyObject_CallNoArgs(curr_task_getters[i]);
|
|
423
425
|
if (!curr_task) {
|
|
424
426
|
PyErr_Clear(); // RuntimeError, probably
|
|
425
427
|
curr_task = Py_None;
|
|
@@ -1202,7 +1204,7 @@ tracer_load(TracerObject* self, PyObject* Py_UNUSED(unused))
|
|
|
1202
1204
|
perror("Failed to access multiprocessing.current_process()");
|
|
1203
1205
|
exit(-1);
|
|
1204
1206
|
}
|
|
1205
|
-
PyObject* current_process =
|
|
1207
|
+
PyObject* current_process = PyObject_CallNoArgs(current_process_method);
|
|
1206
1208
|
if (!current_process_method) {
|
|
1207
1209
|
perror("Failed to access multiprocessing.current_process()");
|
|
1208
1210
|
exit(-1);
|
|
@@ -1270,7 +1272,7 @@ tracer_load(TracerObject* self, PyObject* Py_UNUSED(unused))
|
|
|
1270
1272
|
PyObject* task_name = NULL;
|
|
1271
1273
|
if (PyObject_HasAttrString(curr->data.fee.asyncio_task, "get_name")) {
|
|
1272
1274
|
PyObject* task_name_method = PyObject_GetAttrString(curr->data.fee.asyncio_task, "get_name");
|
|
1273
|
-
task_name =
|
|
1275
|
+
task_name = PyObject_CallNoArgs(task_name_method);
|
|
1274
1276
|
Py_DECREF(task_name_method);
|
|
1275
1277
|
} else if (PyObject_HasAttrString(curr->data.fee.asyncio_task, "name")) {
|
|
1276
1278
|
task_name = PyObject_GetAttrString(curr->data.fee.asyncio_task, "name");
|
|
@@ -1456,7 +1458,7 @@ tracer_dump(TracerObject* self, PyObject* args, PyObject* kw)
|
|
|
1456
1458
|
perror("Failed to access multiprocessing.current_process()");
|
|
1457
1459
|
exit(-1);
|
|
1458
1460
|
}
|
|
1459
|
-
PyObject* current_process =
|
|
1461
|
+
PyObject* current_process = PyObject_CallNoArgs(current_process_method);
|
|
1460
1462
|
if (!current_process_method) {
|
|
1461
1463
|
perror("Failed to access multiprocessing.current_process()");
|
|
1462
1464
|
exit(-1);
|
|
@@ -1502,7 +1504,7 @@ tracer_dump(TracerObject* self, PyObject* args, PyObject* kw)
|
|
|
1502
1504
|
PyObject* task_name = NULL;
|
|
1503
1505
|
if (PyObject_HasAttrString(curr->data.fee.asyncio_task, "get_name")) {
|
|
1504
1506
|
PyObject* task_name_method = PyObject_GetAttrString(curr->data.fee.asyncio_task, "get_name");
|
|
1505
|
-
task_name =
|
|
1507
|
+
task_name = PyObject_CallNoArgs(task_name_method);
|
|
1506
1508
|
Py_DECREF(task_name_method);
|
|
1507
1509
|
} else if (PyObject_HasAttrString(curr->data.fee.asyncio_task, "name")) {
|
|
1508
1510
|
task_name = PyObject_GetAttrString(curr->data.fee.asyncio_task, "name");
|
|
@@ -1686,7 +1688,7 @@ tracer_getbasetime(TracerObject* self, PyObject* Py_UNUSED(unused))
|
|
|
1686
1688
|
}
|
|
1687
1689
|
|
|
1688
1690
|
static PyObject*
|
|
1689
|
-
|
|
1691
|
+
tracer_resetstack(TracerObject* self, PyObject* Py_UNUSED(unused))
|
|
1690
1692
|
{
|
|
1691
1693
|
struct ThreadInfo* info = get_thread_info(self);
|
|
1692
1694
|
if (!info) {
|
|
@@ -1694,12 +1696,12 @@ tracer_setcurrstack(TracerObject* self, PyObject* stack_depth)
|
|
|
1694
1696
|
return NULL;
|
|
1695
1697
|
}
|
|
1696
1698
|
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
return NULL;
|
|
1700
|
-
}
|
|
1699
|
+
info->curr_stack_depth = 0;
|
|
1700
|
+
info->ignore_stack_depth = 0;
|
|
1701
1701
|
|
|
1702
|
-
|
|
1702
|
+
struct FunctionNode* stack_top = info->stack_top;
|
|
1703
|
+
clear_stack(&stack_top);
|
|
1704
|
+
info->stack_top = stack_top;
|
|
1703
1705
|
|
|
1704
1706
|
Py_RETURN_NONE;
|
|
1705
1707
|
}
|
|
@@ -1978,7 +1980,7 @@ static PyMethodDef Tracer_methods[] = {
|
|
|
1978
1980
|
{"get_func_args", (PyCFunction)tracer_getfunctionarg, METH_NOARGS, "get current function arg"},
|
|
1979
1981
|
{"getts", (PyCFunction)tracer_getts, METH_NOARGS, "get timestamp"},
|
|
1980
1982
|
{"get_base_time", (PyCFunction)tracer_getbasetime, METH_NOARGS, "get base time in nanoseconds"},
|
|
1981
|
-
{"
|
|
1983
|
+
{"reset_stack", (PyCFunction)tracer_resetstack, METH_NOARGS, "reset stack"},
|
|
1982
1984
|
{"pause", (PyCFunction)tracer_pause, METH_NOARGS, "pause profiling"},
|
|
1983
1985
|
{"resume", (PyCFunction)tracer_resume, METH_NOARGS, "resume profiling"},
|
|
1984
1986
|
{"setignorestackcounter", (PyCFunction)tracer_setignorestackcounter, METH_O, "reset ignore stack depth"},
|
viztracer/modules/util.c
CHANGED
|
@@ -20,13 +20,9 @@ void
|
|
|
20
20
|
fprintjson(FILE* fptr, PyObject* obj)
|
|
21
21
|
{
|
|
22
22
|
PyObject* json_dumps = PyObject_GetAttrString(json_module, "dumps");
|
|
23
|
-
PyObject*
|
|
24
|
-
PyTuple_SetItem(call_args, 0, obj);
|
|
25
|
-
Py_INCREF(obj);
|
|
26
|
-
PyObject* args_str = PyObject_CallObject(json_dumps, call_args);
|
|
23
|
+
PyObject* args_str = PyObject_CallOneArg(json_dumps, obj);
|
|
27
24
|
fprintf(fptr, "%s", PyUnicode_AsUTF8(args_str));
|
|
28
25
|
Py_DECREF(json_dumps);
|
|
29
|
-
Py_DECREF(call_args);
|
|
30
26
|
Py_DECREF(args_str);
|
|
31
27
|
}
|
|
32
28
|
|
|
@@ -188,7 +188,6 @@ PyObject*
|
|
|
188
188
|
json_dumps_to_bytes(PyObject* json_data)
|
|
189
189
|
{
|
|
190
190
|
PyObject* json_ret = NULL;
|
|
191
|
-
PyObject* json_args = NULL;
|
|
192
191
|
PyObject* bytes_data = NULL;
|
|
193
192
|
PyObject* dumps_func = NULL;
|
|
194
193
|
|
|
@@ -202,11 +201,7 @@ json_dumps_to_bytes(PyObject* json_data)
|
|
|
202
201
|
}
|
|
203
202
|
|
|
204
203
|
// json dumps json_data
|
|
205
|
-
|
|
206
|
-
PyTuple_SetItem(json_args, 0, json_data);
|
|
207
|
-
Py_INCREF(json_data);
|
|
208
|
-
json_ret = PyObject_CallObject(dumps_func, json_args);
|
|
209
|
-
Py_DECREF(json_args);
|
|
204
|
+
json_ret = PyObject_CallOneArg(dumps_func, json_data);
|
|
210
205
|
if (!json_ret) {
|
|
211
206
|
goto clean_exit;
|
|
212
207
|
}
|
|
@@ -240,7 +235,6 @@ json_loads_from_bytes(PyObject* bytes_data)
|
|
|
240
235
|
{
|
|
241
236
|
PyObject* loads_func = NULL;
|
|
242
237
|
PyObject* string_data = NULL;
|
|
243
|
-
PyObject* json_args = NULL;
|
|
244
238
|
PyObject* json_data = NULL;
|
|
245
239
|
|
|
246
240
|
if (!PyBytes_Check(bytes_data)) {
|
|
@@ -261,10 +255,7 @@ json_loads_from_bytes(PyObject* bytes_data)
|
|
|
261
255
|
}
|
|
262
256
|
|
|
263
257
|
// convert string to json
|
|
264
|
-
|
|
265
|
-
PyTuple_SetItem(json_args, 0, string_data);
|
|
266
|
-
json_data = PyObject_CallObject(loads_func, json_args);
|
|
267
|
-
Py_DECREF(json_args);
|
|
258
|
+
json_data = PyObject_CallOneArg(loads_func, string_data);
|
|
268
259
|
if (!json_data) {
|
|
269
260
|
goto clean_exit;
|
|
270
261
|
}
|
|
@@ -283,7 +274,6 @@ clean_exit:
|
|
|
283
274
|
PyObject*
|
|
284
275
|
compress_bytes(PyObject* bytes_data)
|
|
285
276
|
{
|
|
286
|
-
PyObject* zlib_args = NULL;
|
|
287
277
|
PyObject* compress_func = NULL;
|
|
288
278
|
PyObject* compressed_data = NULL;
|
|
289
279
|
|
|
@@ -298,12 +288,7 @@ compress_bytes(PyObject* bytes_data)
|
|
|
298
288
|
goto clean_exit;
|
|
299
289
|
}
|
|
300
290
|
|
|
301
|
-
|
|
302
|
-
PyTuple_SetItem(zlib_args, 0, bytes_data);
|
|
303
|
-
Py_INCREF(bytes_data);
|
|
304
|
-
compressed_data = PyObject_CallObject(compress_func, zlib_args);
|
|
305
|
-
// zlib_args steals bytes_data, so release zlib_args will release bytes_data
|
|
306
|
-
Py_DECREF(zlib_args);
|
|
291
|
+
compressed_data = PyObject_CallOneArg(compress_func, bytes_data);
|
|
307
292
|
if (!compressed_data) {
|
|
308
293
|
goto clean_exit;
|
|
309
294
|
}
|
|
@@ -328,7 +313,6 @@ PyObject*
|
|
|
328
313
|
decompress_bytes(PyObject* bytes_data)
|
|
329
314
|
{
|
|
330
315
|
// decompress data
|
|
331
|
-
PyObject* zlib_args = NULL;
|
|
332
316
|
PyObject* decompressed_data = NULL;
|
|
333
317
|
PyObject* decompress_func = NULL;
|
|
334
318
|
|
|
@@ -343,11 +327,7 @@ decompress_bytes(PyObject* bytes_data)
|
|
|
343
327
|
goto clean_exit;
|
|
344
328
|
}
|
|
345
329
|
|
|
346
|
-
|
|
347
|
-
PyTuple_SetItem(zlib_args, 0, bytes_data);
|
|
348
|
-
Py_INCREF(bytes_data);
|
|
349
|
-
decompressed_data = PyObject_CallObject(decompress_func, zlib_args);
|
|
350
|
-
Py_DECREF(zlib_args);
|
|
330
|
+
decompressed_data = PyObject_CallOneArg(decompress_func, bytes_data);
|
|
351
331
|
if (!decompressed_data) {
|
|
352
332
|
goto clean_exit;
|
|
353
333
|
}
|
|
@@ -95,17 +95,17 @@ parse_trace_events(PyObject* trace_events)
|
|
|
95
95
|
Py_INCREF(pid);
|
|
96
96
|
Py_INCREF(tid);
|
|
97
97
|
Py_INCREF(name);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
PyTuple_SET_ITEM(key, 0, pid);
|
|
99
|
+
PyTuple_SET_ITEM(key, 1, tid);
|
|
100
|
+
PyTuple_SET_ITEM(key, 2, name);
|
|
101
101
|
|
|
102
102
|
// This indicates that if there's args in fee
|
|
103
103
|
fee_args = PyDict_GetItemString(event, "args");
|
|
104
104
|
if (fee_args) {
|
|
105
|
-
|
|
105
|
+
PyTuple_SET_ITEM(key, 3, Py_True);
|
|
106
106
|
Py_INCREF(Py_True);
|
|
107
107
|
} else {
|
|
108
|
-
|
|
108
|
+
PyTuple_SET_ITEM(key, 3, Py_False);
|
|
109
109
|
Py_INCREF(Py_False);
|
|
110
110
|
}
|
|
111
111
|
|
|
@@ -126,11 +126,11 @@ parse_trace_events(PyObject* trace_events)
|
|
|
126
126
|
|
|
127
127
|
Py_INCREF(ts);
|
|
128
128
|
Py_INCREF(dur);
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
PyTuple_SET_ITEM(ts_dur_tuple, 0, ts);
|
|
130
|
+
PyTuple_SET_ITEM(ts_dur_tuple, 1, dur);
|
|
131
131
|
|
|
132
132
|
if (fee_args) {
|
|
133
|
-
|
|
133
|
+
PyTuple_SET_ITEM(ts_dur_tuple, 2, fee_args);
|
|
134
134
|
Py_INCREF(fee_args);
|
|
135
135
|
}
|
|
136
136
|
|
|
@@ -154,8 +154,8 @@ parse_trace_events(PyObject* trace_events)
|
|
|
154
154
|
// PyTuple_SetItem steals reference
|
|
155
155
|
Py_INCREF(pid);
|
|
156
156
|
Py_INCREF(tid);
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
PyTuple_SET_ITEM(id_key, 0, pid);
|
|
158
|
+
PyTuple_SET_ITEM(id_key, 1, tid);
|
|
159
159
|
|
|
160
160
|
if (PyUnicode_CompareWithASCIIString(name, "process_name") == 0) {
|
|
161
161
|
PyDict_SetItem(process_names, id_key, args_name);
|
|
@@ -185,9 +185,9 @@ parse_trace_events(PyObject* trace_events)
|
|
|
185
185
|
Py_INCREF(name);
|
|
186
186
|
Py_INCREF(pid);
|
|
187
187
|
Py_INCREF(tid);
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
188
|
+
PyTuple_SET_ITEM(counter_id_key, 0, pid);
|
|
189
|
+
PyTuple_SET_ITEM(counter_id_key, 1, tid);
|
|
190
|
+
PyTuple_SET_ITEM(counter_id_key, 2, name);
|
|
191
191
|
if (!PyDict_Contains(counter_events, counter_id_key)){
|
|
192
192
|
counter_event_dict = PyDict_New();
|
|
193
193
|
PyDict_SetItem(counter_events, counter_id_key, counter_event_dict);
|
viztracer/patch.py
CHANGED
|
@@ -10,7 +10,7 @@ import shutil
|
|
|
10
10
|
import sys
|
|
11
11
|
import textwrap
|
|
12
12
|
from multiprocessing import Process
|
|
13
|
-
from typing import Any, Callable, Sequence,
|
|
13
|
+
from typing import Any, Callable, Sequence, no_type_check
|
|
14
14
|
|
|
15
15
|
from .viztracer import VizTracer
|
|
16
16
|
|
|
@@ -28,7 +28,7 @@ def patch_subprocess(viz_args: list[str]) -> None:
|
|
|
28
28
|
|
|
29
29
|
def build_command(args: Sequence[str]) -> list[str] | None:
|
|
30
30
|
py_args: list[str] = []
|
|
31
|
-
mode = []
|
|
31
|
+
mode: list[str] | None = []
|
|
32
32
|
script = None
|
|
33
33
|
args_iter = iter(args[1:])
|
|
34
34
|
for arg in args_iter:
|
|
@@ -51,7 +51,11 @@ def patch_subprocess(viz_args: list[str]) -> None:
|
|
|
51
51
|
py_args.append(f"-{cm_py_args}")
|
|
52
52
|
mode = [f"-{cm}"]
|
|
53
53
|
# -m mod | -mmod
|
|
54
|
-
|
|
54
|
+
cm_arg = cm_arg or next(args_iter, None)
|
|
55
|
+
if cm_arg is not None:
|
|
56
|
+
mode.append(cm_arg)
|
|
57
|
+
else:
|
|
58
|
+
mode = None
|
|
55
59
|
break
|
|
56
60
|
|
|
57
61
|
# -pyopts
|
|
@@ -59,7 +63,7 @@ def patch_subprocess(viz_args: list[str]) -> None:
|
|
|
59
63
|
|
|
60
64
|
if script:
|
|
61
65
|
return [sys.executable, *py_args, "-m", "viztracer", "--quiet", *viz_args, "--", script, *args_iter]
|
|
62
|
-
elif mode
|
|
66
|
+
elif mode:
|
|
63
67
|
return [sys.executable, *py_args, "-m", "viztracer", "--quiet", *viz_args, *mode, "--", *args_iter]
|
|
64
68
|
return None
|
|
65
69
|
|
|
@@ -78,7 +82,7 @@ def patch_subprocess(viz_args: list[str]) -> None:
|
|
|
78
82
|
return False
|
|
79
83
|
|
|
80
84
|
@functools.wraps(subprocess.Popen.__init__)
|
|
81
|
-
def subprocess_init(self: subprocess.Popen[Any], args:
|
|
85
|
+
def subprocess_init(self: subprocess.Popen[Any], args: str | Sequence[Any] | Any, **kwargs: Any) -> None:
|
|
82
86
|
new_args = args
|
|
83
87
|
if isinstance(new_args, str):
|
|
84
88
|
new_args = shlex.split(new_args, posix=sys.platform != "win32")
|
|
@@ -118,7 +122,7 @@ def patch_multiprocessing(tracer: VizTracer, viz_args: list[str]) -> None:
|
|
|
118
122
|
tracer.register_exit()
|
|
119
123
|
|
|
120
124
|
tracer.clear()
|
|
121
|
-
tracer.
|
|
125
|
+
tracer.reset_stack()
|
|
122
126
|
|
|
123
127
|
if tracer._afterfork_cb:
|
|
124
128
|
tracer._afterfork_cb(tracer, *tracer._afterfork_args, **tracer._afterfork_kwargs)
|
viztracer/report_builder.py
CHANGED
|
@@ -12,13 +12,13 @@ import os
|
|
|
12
12
|
import re
|
|
13
13
|
import tokenize
|
|
14
14
|
from string import Template
|
|
15
|
-
from typing import Any,
|
|
15
|
+
from typing import Any, Sequence, TextIO
|
|
16
16
|
|
|
17
17
|
from . import __version__
|
|
18
18
|
from .util import color_print, same_line_print
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
def get_json(data:
|
|
21
|
+
def get_json(data: dict[str, Any] | str | tuple[str, dict]) -> dict[str, Any]:
|
|
22
22
|
# This function will return a json object if data is already json object
|
|
23
23
|
# or a opened file or a file path
|
|
24
24
|
if isinstance(data, dict):
|
|
@@ -65,11 +65,11 @@ def get_json(data: Union[dict, str, tuple[str, dict]]) -> dict[str, Any]:
|
|
|
65
65
|
class ReportBuilder:
|
|
66
66
|
def __init__(
|
|
67
67
|
self,
|
|
68
|
-
data:
|
|
68
|
+
data: Sequence[str | dict | tuple[str, dict]] | dict[str, Any],
|
|
69
69
|
verbose: int = 1,
|
|
70
70
|
align: bool = False,
|
|
71
71
|
minimize_memory: bool = False,
|
|
72
|
-
base_time:
|
|
72
|
+
base_time: int | None = None) -> None:
|
|
73
73
|
self.data = data
|
|
74
74
|
self.verbose = verbose
|
|
75
75
|
self.combined_json: dict = {}
|
|
@@ -145,7 +145,7 @@ class ReportBuilder:
|
|
|
145
145
|
self.combined_json["file_info"]["files"].update(one["file_info"]["files"])
|
|
146
146
|
self.combined_json["file_info"]["functions"].update(one["file_info"]["functions"])
|
|
147
147
|
|
|
148
|
-
def align_events(self, original_events: list[dict[str, Any]], sync_marker:
|
|
148
|
+
def align_events(self, original_events: list[dict[str, Any]], sync_marker: float | None = None) -> list[dict[str, Any]]:
|
|
149
149
|
"""
|
|
150
150
|
Apply an offset to all the trace events, making the start timestamp 0
|
|
151
151
|
This is useful when comparing multiple runs of the same script
|
|
@@ -164,7 +164,7 @@ class ReportBuilder:
|
|
|
164
164
|
event["ts"] -= offset_ts
|
|
165
165
|
return original_events
|
|
166
166
|
|
|
167
|
-
def prepare_json(self, file_info: bool = True, display_time_unit:
|
|
167
|
+
def prepare_json(self, file_info: bool = True, display_time_unit: str | None = None) -> None:
|
|
168
168
|
# This will prepare self.combined_json to be ready to output
|
|
169
169
|
self.load_jsons()
|
|
170
170
|
self.combine_json()
|
|
@@ -208,7 +208,7 @@ class ReportBuilder:
|
|
|
208
208
|
del func_dict[func]
|
|
209
209
|
|
|
210
210
|
@classmethod
|
|
211
|
-
def get_source_from_filename(cls, filename: str) ->
|
|
211
|
+
def get_source_from_filename(cls, filename: str) -> str | None:
|
|
212
212
|
if filename.startswith("<frozen "):
|
|
213
213
|
m = re.match(r"<frozen (.*)>", filename)
|
|
214
214
|
if not m:
|
|
@@ -258,7 +258,7 @@ class ReportBuilder:
|
|
|
258
258
|
else:
|
|
259
259
|
output_file.write(json.dumps(self.combined_json)) # type: ignore
|
|
260
260
|
|
|
261
|
-
def save(self, output_file:
|
|
261
|
+
def save(self, output_file: str | TextIO = "result.html", file_info: bool = True) -> None:
|
|
262
262
|
if isinstance(output_file, str):
|
|
263
263
|
file_type = output_file.split(".")[-1]
|
|
264
264
|
|
|
Binary file
|