@@ -27,14 +27,32 @@ def get_args():
27
27
help = "Path of the MMTk binary" )
28
28
parser .add_argument ("-H" , "--harness" , action = "store_true" ,
29
29
help = "Only collect data for the timing iteration (harness_begin/harness_end)" )
30
- parser .add_argument ("-p" , "--print-script" , action = "store_true" ,
31
- help = "Print the content of the bpftrace script" )
32
30
parser .add_argument ("-e" , "--every" , metavar = "N" , type = int , default = 1 ,
33
31
help = "Only capture every N-th GC" ),
34
32
parser .add_argument ("-x" , "--extra" , metavar = "S" , type = str , action = "append" ,
35
33
help = "Append script S after 'capture.bt'. Use this option multiple times to append multiple scripts." ),
34
+ parser .add_argument ("--no-root-nodes" , action = "store_true" ,
35
+ help = "Do not add 'process_root_nodes' probe." +
36
+ " This USDT is conditionally generated by Rust generics, and may not exist in some VM bindings." )
37
+ parser .add_argument ("-p" , "--print-script" , action = "store_true" ,
38
+ help = "Print the content of the bpftrace script" )
39
+ parser .add_argument ("-d" , "--dry-run" , action = "store_true" ,
40
+ help = "Print the bpftrace command to be executed, but does not actually execute the command. Useful with -p" )
41
+ parser .add_argument ("-v" , "--verbose" , action = "store_true" ,
42
+ help = "Add -v to the bpftrace command. Useful for debugging" ),
36
43
return parser .parse_args ()
37
44
45
+ def delete_lines_between (lines , begin , end ):
46
+ begin_index , end_index = None , None
47
+ for i , line in enumerate (lines ):
48
+ if begin in line and begin_index is None :
49
+ begin_index = i
50
+ if begin_index is not None and end in line :
51
+ end_index = i
52
+ break
53
+ else :
54
+ raise Exception (f"Cannot find { begin } and { end } in the script. { begin_index } { end_index } " )
55
+ del lines [begin_index :end_index + 1 ]
38
56
39
57
def main ():
40
58
args = get_args ()
@@ -48,12 +66,15 @@ def main():
48
66
if args .extra is not None :
49
67
for extra_script in args .extra :
50
68
script_paths .append (Path (extra_script ))
51
- script_texts = []
69
+ scripts_lines = []
52
70
for script_path in script_paths :
53
- script_text = script_path .read_text ()
54
- script_texts . append ( script_text )
71
+ script_lines = script_path .read_text (). splitlines ()
72
+ scripts_lines . extend ( script_lines )
55
73
56
- merged_script = "\n " .join (script_texts )
74
+ if args .no_root_nodes :
75
+ delete_lines_between (scripts_lines , "BEGIN:PROCESS_ROOT_NODES" , "END:PROCESS_ROOT_NODES" )
76
+
77
+ merged_script = "\n " .join (scripts_lines )
57
78
58
79
template = Template (merged_script )
59
80
with tempfile .NamedTemporaryFile (mode = "w+t" ) as tmp :
@@ -66,17 +87,28 @@ def main():
66
87
print (content )
67
88
tmp .write (content )
68
89
tmp .flush ()
69
- # We use execvp to replace the current process instead of creating
70
- # a subprocess (or sh -c). This is so that when users invoke this from
71
- # the command line, Ctrl-C will be captured by bpftrace instead of the
72
- # outer Python script. The temporary file can then be cleaned up by
73
- # the END probe in bpftrace.
74
- #
75
- # In theory, you can implement this via pty, but it is very finicky
76
- # and doesn't work reliably.
77
- # See also https://github.com/anupli/running-ng/commit/b74e3a13f56dd97f73432d8a391e1d6cd9db8663
78
- os .execvp ("sudo" , ["sudo" , args .bpftrace ,
79
- "--unsafe" , tmp .name ])
90
+
91
+ extra_options = []
92
+ if args .verbose :
93
+ extra_options .append ("-v" )
94
+
95
+ command_line = ["sudo" , args .bpftrace ] + extra_options + ["--unsafe" , tmp .name ]
96
+
97
+ if args .dry_run :
98
+ print ("Dry run. Command to execute:" )
99
+ print (" " .join (f"'{ c } '" for c in command_line ))
100
+ # tempfile will be deleted at the end of `with`.
101
+ else :
102
+ # We use execvp to replace the current process instead of creating
103
+ # a subprocess (or sh -c). This is so that when users invoke this from
104
+ # the command line, Ctrl-C will be captured by bpftrace instead of the
105
+ # outer Python script. The temporary file can then be cleaned up by
106
+ # the END probe in bpftrace.
107
+ #
108
+ # In theory, you can implement this via pty, but it is very finicky
109
+ # and doesn't work reliably.
110
+ # See also https://github.com/anupli/running-ng/commit/b74e3a13f56dd97f73432d8a391e1d6cd9db8663
111
+ os .execvp ("sudo" , command_line )
80
112
81
113
82
114
if __name__ == "__main__" :
0 commit comments