Simple python library for generating your own perfetto traces for your application.
Example code (see tg4perfetto/example_profile.py for the code)
import tg4perfetto import threading # A "stat" counter. This can be used to log integers or floating-point stats. count_stats = tg4perfetto.count("num_active_threads") # Normally, tracks are assigned to its thread's default track. This creates a custom track custom_track = tg4perfetto.track("TOP_TRACK") # Log the event on a thread-default track. trace_func_args logs the arguments put on the # function, so be careful @tg4perfetto.trace_func_args def merge(x, x1, x2): # ... (omitted) def merge_sort_wrapper(x, flow_id): # Instant events tg4perfetto.instant("START_THREAD", incoming_flow_ids = [flow_id[0]]) custom_track.instant("START_THREAD", incoming_flow_ids = [flow_id[1]]) return merge_sort(x) def merge_sort_threaded(x): # Instant event. Has two "flow ID" which can be used for connecting two events. flow_ids = tg4perfetto.instant("INVOKE_THREAD", num_outgoing_flow_ids = 2) t = threading.Thread(target=merge_sort_wrapper, args=(x,flow_ids)) t.start() return (x, t) # Log the event on a thread-default track. Unlike trace_func_args, trace_func # only logs the call in/out events. @tg4perfetto.trace_func def merge_sort(x): l = len(x) if l < 4096: return sorted(x) if l < 40000: x1 = merge_sort(x[:int(l/2)]) x2 = merge_sort(x[int(l/2):]) else: # Using count_stats to increment and decrement count_stats.increment(1) x1, t1 = merge_sort_threaded(x[:int(l/2)]) count_stats.increment(1) x2, t2 = merge_sort_threaded(x[int(l/2):]) t1.join() count_stats.increment(-1) t2.join() count_stats.increment(-1) return merge(x, x1, x2) # Log the event on the given specific track. @tg4perfetto.trace_func(custom_track) def validate(xarray): # ... (omitted) if __name__ == "__main__": # Start logging. Logging stops when this goes out of scope. with tg4perfetto.open("tg4p.perfetto-trace"): # Use a custom track. # to put into the default track. just use tg4perfetto.trace(...) instead. with custom_track.trace('SORT').get_outgoing_flow_ids(1) as out_flow_id: xarray = [ (17 * x + 8) % 100 for x in range(100000) ] xarray = merge_sort(xarray) # Create one flow ID from the current track. We can create flow IDs before closing the track. p = out_flow_id[0] # Set the incoming flow ID (optional, set only if there are any). with custom_track.trace('VALIDATE').set_incoming_flow_ids([p]): tg4perfetto.instant("CHECKING", {"final_result": xarray}) validate(xarray) print("Done") This will generate a trace file named "tg4p.perfetto-trace" which can be read from perfetto.
Example code (see tg4perfetto/example.py for the code)
# Packets can be created out-of-order. This is because perfetto is designed to process out-of-order traces # and reads all packets at once, rearranges them, and then visualizes it at once. tgen = TraceGenerator(sys.argv[1]) pid = tgen.create_group("aaa", "example_track") pid.open(100, "SOME_TRACK") # "Flow" packet. this will create an arrow from here to "open" event down there (400ns) pid.close(250, [4]) # Global counter track tid = tgen.create_counter_track("bbb") tid.count(0, 3) tid.count(200, 5) tid.count(400, 7) tid.count(700, 2) # Counter track within the "aaa" group" tid = pid.create_counter_track("bbb") tid.count(0, 2) tid.count(200, 4) tid.count(400, 5) tid.count(700, 1) tid = pid.create_track("ddd") tid.open(100, "WXX") # another "flow" packet. tid.close(300, [3]) tgen.flush() pid = tgen.create_group("vvv") tid = pid.create_counter_track("bbb2") tid.count(0, 2) tid.count(300, 400) tid.count(400, 500) tid.count(700, 1000) tid = pid.create_track("ddd2") tid2 = pid.create_track("ddd3") tid2.instant(200, "WXYZ") tid.open(222, "XXX") tid2.open(300, "WXX3", {"aaa":"bbb", "ccc":"ddd"}) tid2.instant(300, "ABCDE", {"aaa": "bbb", "ccc": "xxx"}) tid.close(333) # receives an arrow from the packet above. this can be either from an instant event or a normal event. tid2.open(400, "WXX4", {"aaa":"bbb", "ccc":"ddd"}, [3, 4]) tid2.instant(400, "ABCDE") # Some annotation on instant event tid2.instant(600, "ADE", {"aaa": "abc", "ccc": "xxx", "eee" : {"aaa": "abc", "ccc": "ddd"}}) tid2.close(670, [2]) # very complex annotations! tid2.instant(700, "ADE2", { "aaa": "abc", "ccc": [1, 2, 3, 4, "a", "b", {"abcdef" : "fdsa", "ggg": True}], "eee" : { "aaa": "abc", "ccc": True, "eee": { "fff": "ggg", "hhh": 0x1234567 } }, "jjj": "kkk" }, [2]) tid2.close(900, [1]) tid.open(900, "WXX2", {"aaa":"bbb", "ccc":"ddd"}, [1]) tid.close(1000) pid4 = tgen.create_group("abc.2") tid4 = pid4.create_group("XX") t1 = tid4.create_track() t2 = tid4.create_track() t1.open(100, "X") t2.open(300, "Y") t1.close(500) t2.close(600) Example output:
