mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 11:50:28 +02:00
Merged Whippet into libguile/whippet
This commit is contained in:
commit
db181e67ff
112 changed files with 18115 additions and 0 deletions
160
libguile/whippet/ctf_to_json.py
Executable file
160
libguile/whippet/ctf_to_json.py
Executable file
|
@ -0,0 +1,160 @@
|
|||
#!/usr/bin/env python3
|
||||
# Any copyright is dedicated to the Public Domain.
|
||||
# https://creativecommons.org/publicdomain/zero/1.0/
|
||||
#
|
||||
# Originally written by Andy Wingo <wingo@igalia.com>.
|
||||
|
||||
import bt2 # From the babeltrace2 package.
|
||||
import sys
|
||||
import json
|
||||
from enum import Enum
|
||||
|
||||
# Usage: ./ctf_to_json.py ~/lttng-traces/name-of-your-trace > foo.json
|
||||
#
|
||||
# Convert a Common Trace Format (CTF) trace, for example as produced by
|
||||
# LTTng, to the JSON-based Trace Event Format (TEF), for example as
|
||||
# consumed by `chrome://tracing`, `https://ui.perfetto.dev/`, or
|
||||
# `https://profiler.firefox.com`.
|
||||
|
||||
# The Trace Event Format is documented here:
|
||||
#
|
||||
# https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview?tab=t.0
|
||||
|
||||
# By default, events are emitted as EventPhase.INSTANT. We also support
|
||||
# rewriting the event stream so as to generate EventPhase.BEGIN /
|
||||
# EventPhase.END events for specific named events.
|
||||
|
||||
synthetic_events = {
|
||||
'gc': ['whippet:mutator_cause_gc',
|
||||
'whippet:restarting_mutators'],
|
||||
'stop-the-world': ['whippet:requesting_stop',
|
||||
'whippet:mutators_stopped'],
|
||||
'trace': ['whippet:prepare_gc',
|
||||
'whippet:restarting_mutators'],
|
||||
'mutator-stopped': ['whippet:mutator_stopping',
|
||||
'whippet:mutator_restarted'],
|
||||
'trace-roots': ['whippet:trace_roots_begin',
|
||||
'whippet:trace_roots_end'],
|
||||
'trace-check-termination': ['whippet:trace_check_termination_begin',
|
||||
'whippet:trace_check_termination_end'],
|
||||
'trace-objects': ['whippet:trace_objects_begin',
|
||||
'whippet:trace_objects_end'],
|
||||
'trace-worker': ['whippet:trace_worker_begin',
|
||||
'whippet:trace_worker_end']
|
||||
}
|
||||
|
||||
class EventPhase(Enum):
|
||||
BEGIN = 'B'
|
||||
END = 'E'
|
||||
COMPLETE = 'X'
|
||||
INSTANT = 'i'
|
||||
COUNTER = 'C'
|
||||
NESTABLE_START = 'b'
|
||||
NESTABLE_INSTANT = 'n'
|
||||
NESTABLE_END = 'e'
|
||||
FLOW_START = 's'
|
||||
FLOW_STEP = 't'
|
||||
FLOW_END = 'f'
|
||||
SAMPLE = 'P'
|
||||
OBJECT_CREATED = 'N'
|
||||
OBJECT_SNAPSHOT = 'O'
|
||||
OBJECT_DESTROYED = 'D'
|
||||
METADATA = 'M'
|
||||
MEMORY_DUMP_GLOBAL = 'V'
|
||||
MEMORY_DUMP_PROCESS = 'V'
|
||||
MARK = 'R'
|
||||
CLOCK_SYNC = 'c'
|
||||
CONTEXT_BEGIN = '('
|
||||
CONTEXT_END = ')'
|
||||
|
||||
base_time = None
|
||||
def event_us(msg):
|
||||
assert(msg.default_clock_snapshot.clock_class.name == 'monotonic')
|
||||
assert(msg.default_clock_snapshot.clock_class.frequency == 1e9)
|
||||
global base_time
|
||||
ns = msg.default_clock_snapshot.value
|
||||
if base_time is None:
|
||||
base_time = ns
|
||||
return (ns - base_time) * 1e-3
|
||||
|
||||
def lower(x):
|
||||
if isinstance(x, str) or isinstance(x, int) or isinstance(x, float):
|
||||
return x
|
||||
if isinstance(x, dict) or isinstance(x, bt2._StructureFieldConst):
|
||||
return {lower(k):lower(v) for k, v in x.items()}
|
||||
if isinstance(x, bt2._BoolValueConst) or isinstance(x, bt2._BoolFieldConst):
|
||||
return bool(x)
|
||||
if isinstance(x, bt2._EnumerationFieldConst):
|
||||
return repr(x)
|
||||
if isinstance(x, bt2._IntegerValueConst) or isinstance(x, bt2._IntegerFieldConst):
|
||||
return int(x)
|
||||
if isinstance(x, bt2._RealValueConst) or isinstance(x, bt2._RealFieldConst):
|
||||
return float(x)
|
||||
if isinstance(x, bt2._StringValueConst) or isinstance(x, bt2._StringFieldConst):
|
||||
return str(x)
|
||||
raise ValueError("Unexpected value from trace", x)
|
||||
|
||||
# Specific Whippet events.
|
||||
synthetic_begin = {}
|
||||
synthetic_end = {}
|
||||
for synthetic, [begin, end] in synthetic_events.items():
|
||||
synthetic_begin[begin] = []
|
||||
synthetic_end[end] = []
|
||||
for synthetic, [begin, end] in synthetic_events.items():
|
||||
synthetic_begin[begin].append(synthetic)
|
||||
synthetic_end[end].append(synthetic)
|
||||
|
||||
def put(str):
|
||||
sys.stdout.write(str)
|
||||
|
||||
need_comma = False
|
||||
def print_event(ev):
|
||||
global need_comma
|
||||
if need_comma:
|
||||
sys.stdout.write(',\n ')
|
||||
else:
|
||||
need_comma = True
|
||||
# It appears to be faster to make a string, then print the string,
|
||||
# than to call json.dump with a file object.
|
||||
# json.dump(ev, sys.stdout, ensure_ascii=False, check_circular=False)
|
||||
put(json.dumps(ev, ensure_ascii=False, check_circular=False))
|
||||
|
||||
def emit_event(msg, name, phase):
|
||||
ev = {'name': name,
|
||||
'cat': 'whippet',
|
||||
'ph': phase.value,
|
||||
'ts': event_us(msg),
|
||||
'pid': lower(msg.event.common_context_field['vpid']),
|
||||
'tid': lower(msg.event.common_context_field['vtid']),
|
||||
'args': lower(msg.event.payload_field)}
|
||||
print_event(ev)
|
||||
def emit_begin_event(msg, name):
|
||||
emit_event(msg, name, EventPhase.BEGIN)
|
||||
def emit_end_event(msg, name):
|
||||
emit_event(msg, name, EventPhase.END)
|
||||
|
||||
def emit_events(msg):
|
||||
emit_event(msg, msg.event.name, EventPhase.INSTANT)
|
||||
for begin in synthetic_begin.get(msg.event.name, []):
|
||||
emit_begin_event(msg, begin)
|
||||
for end in synthetic_end.get(msg.event.name, []):
|
||||
emit_end_event(msg, end)
|
||||
|
||||
def ctf_to_json(path):
|
||||
msg_it = bt2.TraceCollectionMessageIterator(path)
|
||||
put('{\n')
|
||||
put(' "traceEvents": [\n ')
|
||||
for msg in msg_it:
|
||||
if hasattr(msg, 'event'):
|
||||
emit_events(msg)
|
||||
put('\n')
|
||||
put('\n ],\n')
|
||||
put(' "displayTimeUnit": "ns"\n')
|
||||
put('}\n')
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
sys.stderr.write(
|
||||
'usage: ' + sys.argv[0] + ' ~/lttng-traces/name-of-your-trace\n')
|
||||
sys.exit(1)
|
||||
else:
|
||||
ctf_to_json(sys.argv[1])
|
Loading…
Add table
Add a link
Reference in a new issue