viztracer 1.0.4__cp311-cp311-win32.whl → 1.1.0__cp311-cp311-win32.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.

Files changed (88) hide show
  1. viztracer/__init__.py +1 -1
  2. viztracer/code_monkey.py +10 -13
  3. viztracer/decorator.py +9 -12
  4. viztracer/event_base.py +2 -2
  5. viztracer/functree.py +7 -7
  6. viztracer/main.py +9 -13
  7. viztracer/modules/snaptrace.c +14 -12
  8. viztracer/modules/util.c +1 -5
  9. viztracer/modules/vcompressor/vc_dump.c +4 -24
  10. viztracer/modules/vcompressor/vcompressor.c +13 -13
  11. viztracer/patch.py +10 -6
  12. viztracer/report_builder.py +8 -8
  13. viztracer/snaptrace.cp311-win32.pyd +0 -0
  14. viztracer/snaptrace.pyi +8 -8
  15. viztracer/util.py +1 -2
  16. viztracer/vcompressor.cp311-win32.pyd +0 -0
  17. viztracer/viewer.py +5 -5
  18. viztracer/vizlogging.py +1 -2
  19. viztracer/vizplugin.py +3 -3
  20. viztracer/viztracer.py +16 -16
  21. viztracer/web_dist/index.html +1 -1
  22. viztracer/web_dist/service_worker.js +103 -1
  23. viztracer/web_dist/trace_processor +32 -31
  24. viztracer/web_dist/v52.0-6b9586def/assets/MaterialSymbolsOutlined.woff2 +0 -0
  25. viztracer/web_dist/v52.0-6b9586def/engine_bundle.js +3 -0
  26. viztracer/web_dist/v52.0-6b9586def/frontend_bundle.js +5495 -0
  27. viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/manifest.json +10 -8
  28. viztracer/web_dist/v52.0-6b9586def/perfetto.css +5737 -0
  29. viztracer/web_dist/v52.0-6b9586def/stdlib_docs.json +1 -0
  30. viztracer/web_dist/v52.0-6b9586def/trace_config_utils.wasm +0 -0
  31. viztracer/web_dist/{v47.0-02b2414d5/traceconv.wasm → v52.0-6b9586def/trace_processor.wasm} +0 -0
  32. viztracer/web_dist/v52.0-6b9586def/trace_processor_memory64.wasm +0 -0
  33. viztracer/web_dist/{v47.0-02b2414d5/trace_processor.wasm → v52.0-6b9586def/traceconv.wasm} +0 -0
  34. viztracer/web_dist/v52.0-6b9586def/traceconv_bundle.js +2 -0
  35. viztracer-1.1.0.dist-info/METADATA +316 -0
  36. viztracer-1.1.0.dist-info/RECORD +109 -0
  37. {viztracer-1.0.4.dist-info → viztracer-1.1.0.dist-info}/WHEEL +1 -1
  38. viztracer/web_dist/v47.0-02b2414d5/assets/._MaterialSymbolsOutlined.woff2 +0 -0
  39. viztracer/web_dist/v47.0-02b2414d5/assets/MaterialSymbolsOutlined.woff2 +0 -0
  40. viztracer/web_dist/v47.0-02b2414d5/engine_bundle.js +0 -3
  41. viztracer/web_dist/v47.0-02b2414d5/frontend_bundle.js +0 -4994
  42. viztracer/web_dist/v47.0-02b2414d5/perfetto.css +0 -5133
  43. viztracer/web_dist/v47.0-02b2414d5/traceconv_bundle.js +0 -2
  44. viztracer-1.0.4.dist-info/METADATA +0 -537
  45. viztracer-1.0.4.dist-info/RECORD +0 -107
  46. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/Roboto-100.woff2 +0 -0
  47. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/Roboto-300.woff2 +0 -0
  48. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/Roboto-400.woff2 +0 -0
  49. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/Roboto-500.woff2 +0 -0
  50. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/RobotoCondensed-Light.woff2 +0 -0
  51. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/RobotoCondensed-Regular.woff2 +0 -0
  52. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/RobotoMono-Regular.woff2 +0 -0
  53. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/brand.png +0 -0
  54. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/catapult_trace_viewer.html +0 -0
  55. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/catapult_trace_viewer.js +0 -0
  56. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/favicon.png +0 -0
  57. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/logo-128.png +0 -0
  58. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/logo-3d.png +0 -0
  59. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_atrace.png +0 -0
  60. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_battery_counters.png +0 -0
  61. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_board_voltage.png +0 -0
  62. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_cpu_coarse.png +0 -0
  63. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_cpu_fine.png +0 -0
  64. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_cpu_freq.png +0 -0
  65. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_cpu_voltage.png +0 -0
  66. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_frame_timeline.png +0 -0
  67. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_ftrace.png +0 -0
  68. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_gpu_mem_total.png +0 -0
  69. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_java_heap_dump.png +0 -0
  70. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_lmk.png +0 -0
  71. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_logcat.png +0 -0
  72. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_long_trace.png +0 -0
  73. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_mem_hifreq.png +0 -0
  74. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_meminfo.png +0 -0
  75. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_native_heap_profiler.png +0 -0
  76. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_one_shot.png +0 -0
  77. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_profiling.png +0 -0
  78. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_ps_stats.png +0 -0
  79. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_ring_buf.png +0 -0
  80. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_syscalls.png +0 -0
  81. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/rec_vmstat.png +0 -0
  82. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/scheduling_latency.png +0 -0
  83. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/assets/vscode-icon.png +0 -0
  84. /viztracer/web_dist/{v47.0-02b2414d5 → v52.0-6b9586def}/index.html +0 -0
  85. {viztracer-1.0.4.dist-info → viztracer-1.1.0.dist-info}/entry_points.txt +0 -0
  86. {viztracer-1.0.4.dist-info → viztracer-1.1.0.dist-info}/licenses/LICENSE +0 -0
  87. {viztracer-1.0.4.dist-info → viztracer-1.1.0.dist-info}/licenses/NOTICE.txt +0 -0
  88. {viztracer-1.0.4.dist-info → viztracer-1.1.0.dist-info}/top_level.txt +0 -0
viztracer/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2
2
  # For details: https://github.com/gaogaotiantian/viztracer/blob/master/NOTICE.txt
3
3
 
4
- __version__ = "1.0.4"
4
+ __version__ = "1.1.0"
5
5
 
6
6
 
7
7
  from .cellmagic import load_ipython_extension
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, Optional, Union
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) -> Union[ast.stmt, list[ast.stmt]]:
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) -> Union[ast.stmt, list[ast.stmt]]:
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) -> Union[ast.stmt, list[ast.stmt]]:
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) -> Union[ast.AST, list[ast.AST]]:
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: Union[ast.Assign, ast.AugAssign, ast.AnnAssign]) -> list[ast.stmt]:
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: Optional[ast.expr]) -> ast.Expr:
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: Union[ast.expr, ast.slice]) -> str:
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
- if isinstance(node.value, str):
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: Optional[SourceProcessor] = None
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, Optional, TypeVar, Union, overload
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: Optional[VizTracer] = None) -> Callable[[Callable[..., R]], Callable[..., R]]:
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: Optional[VizTracer] = None) -> Callable[..., R]:
24
+ tracer: VizTracer | None = None) -> Callable[..., R]:
25
25
  pass # pragma: no cover
26
26
 
27
27
 
28
- def ignore_function(method: Optional[Callable[..., R]] = None,
29
- tracer: Optional[VizTracer] = None) -> Union[Callable[..., R],
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: Optional[Callable[..., R]] = None,
67
+ def trace_and_save(method: Callable[..., R] | None = None,
69
68
  output_dir: str = "./",
70
- **viztracer_kwargs) -> Union[Callable[..., R],
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: Optional[Callable[..., R]] = None,
159
+ def log_sparse(func: Callable[..., R] | None = None,
162
160
  stack_depth: int = 0,
163
- dynamic_tracer_check: bool = False) -> Union[Callable[..., R],
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, Optional
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: Optional[Callable] = None,
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, Optional
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: Optional[dict[str, Any]] = None) -> None:
14
- self.filename: Optional[str] = None
15
- self.lineno: Optional[int] = None
16
- self.is_python: Optional[bool] = False
17
- self.funcname: Optional[str] = None
18
- self.parent: Optional[FuncTreeNode] = None
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, Optional, Union
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, Optional[str]]
34
+ VizProcedureResult = tuple[bool, str | None]
35
35
 
36
36
 
37
37
  class VizUI:
38
38
  def __init__(self) -> None:
39
- self.tracer: Optional[VizTracer] = None
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: Optional[int] = None
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) -> Optional[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: Union[CodeType, str], global_dict: dict[str, Any]) -> VizProcedureResult:
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, Optional[str]]:
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
 
@@ -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 = PyObject_CallObject(curr_task_getters[i], NULL);
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 = PyObject_CallObject(current_process_method, NULL);
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 = PyObject_CallObject(task_name_method, NULL);
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 = PyObject_CallObject(current_process_method, NULL);
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 = PyObject_CallObject(task_name_method, NULL);
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
- tracer_setcurrstack(TracerObject* self, PyObject* stack_depth)
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
- if (!PyLong_Check(stack_depth)) {
1698
- PyErr_SetString(PyExc_TypeError, "stack_depth must be an integer");
1699
- return NULL;
1700
- }
1699
+ info->curr_stack_depth = 0;
1700
+ info->ignore_stack_depth = 0;
1701
1701
 
1702
- info->curr_stack_depth = PyLong_AsLong(stack_depth);
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
- {"_set_curr_stack_depth", (PyCFunction)tracer_setcurrstack, METH_O, "set current stack depth"},
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* call_args = PyTuple_New(1);
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
- json_args = PyTuple_New(1);
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
- json_args = PyTuple_New(1);
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
- zlib_args = PyTuple_New(1);
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
- zlib_args = PyTuple_New(1);
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
- PyTuple_SetItem(key, 0, pid);
99
- PyTuple_SetItem(key, 1, tid);
100
- PyTuple_SetItem(key, 2, name);
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
- PyTuple_SetItem(key, 3, Py_True);
105
+ PyTuple_SET_ITEM(key, 3, Py_True);
106
106
  Py_INCREF(Py_True);
107
107
  } else {
108
- PyTuple_SetItem(key, 3, Py_False);
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
- PyTuple_SetItem(ts_dur_tuple, 0, ts);
130
- PyTuple_SetItem(ts_dur_tuple, 1, dur);
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
- PyTuple_SetItem(ts_dur_tuple, 2, fee_args);
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
- PyTuple_SetItem(id_key, 0, pid);
158
- PyTuple_SetItem(id_key, 1, tid);
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
- PyTuple_SetItem(counter_id_key, 0, pid);
189
- PyTuple_SetItem(counter_id_key, 1, tid);
190
- PyTuple_SetItem(counter_id_key, 2, name);
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, Union, no_type_check
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
- mode.append(cm_arg or next(args_iter, None))
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 and mode[-1] is not None:
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: Union[str, Sequence[Any], Any], **kwargs: Any) -> None:
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._set_curr_stack_depth(1)
125
+ tracer.reset_stack()
122
126
 
123
127
  if tracer._afterfork_cb:
124
128
  tracer._afterfork_cb(tracer, *tracer._afterfork_args, **tracer._afterfork_kwargs)
@@ -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, Optional, Sequence, TextIO, Union
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: Union[dict, str, tuple[str, dict]]) -> dict[str, Any]:
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: Union[Sequence[Union[str, dict, tuple[str, dict]]], dict],
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: Optional[int] = None) -> None:
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: Optional[float] = None) -> list[dict[str, Any]]:
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: Optional[str] = None) -> None:
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) -> Optional[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: Union[str, TextIO] = "result.html", file_info: bool = True) -> None:
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