[tools] Fix Python scripts for processing --trace-gc-nvp

The Python scripts used for processing `--trace-gc-nvp` logs expect
that all lines in the trace log have the same fields. For different
types of GCs (full, scavenger, minor-ms) what is actually printed is
however different. With this CL, tools/gc-nvp-to-csv.py now:

1. takes the union of the fields of all lines in the log, appropriately
   merging; and
2. preserves the order of the fields (they were previously arbitrarily
   reordered).

Change-Id: I4a7d40d86698391929e4f0a19c96c03fe0e8c804
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4714697
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Nikolaos Papaspyrou <nikolaos@chromium.org>
Cr-Commit-Position: refs/heads/main@{#89201}
This commit is contained in:
Nikolaos Papaspyrou authored and V8 LUCI CQ committed 2023-07-26 10:34:30 +00:00
1 parent b41676c18b
commit 8be7c75883
2 files changed
+67 -20

No files matched your search

+23 -12
View File
@@ -5,31 +5,42 @@
# found in the LICENSE file.
#
# This is an utility for generating csv files based on GC traces produced by
# This is a utility for generating csv files based on GC traces produced by
# V8 when run with flags --trace-gc --trace-gc-nvp.
#
# Usage: gc-nvp-to-csv.py <GC-trace-filename>
# Usage: gc-nvp-to-csv.py [-h] [filename]
#
# for py2/py3 compatibility
from __future__ import print_function
import argparse
import sys
import gc_nvp_common
def process_trace(filename):
trace = gc_nvp_common.parse_gc_trace(filename)
if len(trace):
keys = trace[0].keys()
print(', '.join(keys))
def process_trace(f):
trace, keys = gc_nvp_common.parse_gc_trace_with_keys(f)
if trace:
print(*keys, sep=', ')
for entry in trace:
print(', '.join(map(lambda key: str(entry[key]), keys)))
print(*(entry.get(key, '') for key in keys), sep=', ')
if len(sys.argv) != 2:
print("Usage: %s <GC-trace-filename>" % sys.argv[0])
sys.exit(1)
def main(args):
if args.filename:
with open(args.filename, 'rt') as f:
process_trace(f)
else:
process_trace(sys.stdin)
process_trace(sys.argv[1])
if __name__ == '__main__':
# Command line options.
parser = argparse.ArgumentParser(
description='Helper script for converting --trace-gc-nvp logs to CSV')
parser.add_argument('filename', type=str, nargs='?', help='GC trace log file')
args = parser.parse_args()
# Call the main function.
main(args)
+44 -8
View File
@@ -10,23 +10,59 @@
from __future__ import with_statement
import re
def split_nvp(s):
t = {}
for (name, value) in re.findall(r"([._\w]+)=([-\w]+(?:\.[0-9]+)?)", s):
for name, value in re.findall(r"([._\w]+)=([-\w]+(?:\.[0-9]+)?)", s):
try:
t[name] = float(value)
except ValueError:
t[name] = value
return t
def split_nvp_with_keys(s):
t, k = {}, []
for name, value in re.findall(r"([._\w]+)=([-\w]+(?:\.[0-9]+)?)", s):
try:
t[name] = float(value)
except ValueError:
t[name] = value
k.append(name)
return t, k
def parse_gc_trace(input):
# If input is string, treat it as a filename and open the file for reading.
if isinstance(input, str):
with open(input, 'rt') as f:
return parse_gc_trace(f)
# Otherwise, treat it as a file-like object.
trace = []
with open(input) as f:
for line in f:
info = split_nvp(line)
if info and 'pause' in info and info['pause'] > 0:
info['i'] = len(trace)
trace.append(info)
for line in input:
info = split_nvp(line)
if info and 'pause' in info and info['pause'] > 0:
info['i'] = len(trace)
trace.append(info)
return trace
def parse_gc_trace_with_keys(input):
# If input is string, treat it as a filename and open the file for reading.
if isinstance(input, str):
with open(input, 'rt') as f:
return parse_gc_trace_with_keys(f)
# Otherwise, treat it as a file-like object.
trace = []
keys = {'i'}
key_list = ['i']
for line in input:
info, info_keys = split_nvp_with_keys(line)
if info and 'pause' in info and info['pause'] > 0:
info['i'] = len(trace)
trace.append(info)
for key in info_keys:
if key not in keys:
keys.add(key)
key_list.append(key)
return trace, key_list