From 02f5eb339a0d7f6ba7daf57cf89a761ef34b8b76 Mon Sep 17 00:00:00 2001 From: Christophe Bedard Date: Thu, 6 Jun 2019 09:22:38 +0200 Subject: [PATCH] Complete basic callback duration processing --- analysis/lttng_models.py | 2 +- analysis/ros_processor.py | 41 +++++++++++++++++++++++++-------------- analysis/to_pandas.py | 17 ++++++++++++++++ process.py | 10 ++++++++-- 4 files changed, 52 insertions(+), 18 deletions(-) create mode 100644 analysis/to_pandas.py diff --git a/analysis/lttng_models.py b/analysis/lttng_models.py index 7128293..88f7e01 100644 --- a/analysis/lttng_models.py +++ b/analysis/lttng_models.py @@ -1,7 +1,7 @@ # Model objects for LTTng traces/events def get_field(event, field_name, default=None): - return event.get(field_name, d=default) + return event.get(field_name, default) def get_name(event): return get_field(event, '_name') diff --git a/analysis/ros_processor.py b/analysis/ros_processor.py index 7a26663..10ee168 100644 --- a/analysis/ros_processor.py +++ b/analysis/ros_processor.py @@ -6,11 +6,11 @@ def ros_process(events): """ Process unpickled events and create ROS model :param events (list(dict(str:str:))): the list of events + :return the processor object """ processor = RosProcessor() - for event in events: - print(f'event: {str(event)}') - processor.handle(event) + processor.process_events(events) + return processor class RosProcessor(): """ @@ -19,7 +19,10 @@ class RosProcessor(): """ def __init__(self): # TODO add other stuff - self.callbacks = [] + # Instances of callback_start for eventual matching + self._callback_starts = {} + # Callback instances, callback_address: end - start + self.callbacks_instances = {} # Link a ROS trace event to its corresponding handling method self._handler_map = { @@ -28,13 +31,17 @@ class RosProcessor(): 'ros2:rclcpp_subscription_callback_start': self._handle_subscription_callback_start, 'ros2:rclcpp_subscription_callback_end': self._handle_subscription_callback_end, } - - def handle(self, event): + + def process_events(self, events): """ - Handle an event - :param event (dict(str:str)): the event to handle + Process events + :param events (list(dict(str:str))): the events to process """ - handler_function = self._handler_map.get(get_name(event), d=None) + for event in events: + self._handle(event) + + def _handle(self, event): + handler_function = self._handler_map.get(get_name(event), None) if handler_function is not None: name = get_name(event) pid = get_field(event, 'vpid', default=get_field(event, 'pid')) @@ -49,13 +56,17 @@ class RosProcessor(): pass def _handle_subscription_callback_added(self, event, metadata): - # TODO - pass + # Add the callback address key and create an empty list + callback_addr = get_field(event, 'callback') + self.callbacks_instances[callback_addr] = [] def _handle_subscription_callback_start(self, event, metadata): - # TODO - pass + callback_addr = get_field(event, 'callback') + self._callback_starts[callback_addr] = metadata.timestamp def _handle_subscription_callback_end(self, event, metadata): - # TODO - pass + callback_addr = get_field(event, 'callback') + start_timestamp = self._callback_starts.pop(callback_addr, None) + if start_timestamp is not None: + duration = metadata.timestamp - start_timestamp + self.callbacks_instances[callback_addr].append(duration) diff --git a/analysis/to_pandas.py b/analysis/to_pandas.py new file mode 100644 index 0000000..9806759 --- /dev/null +++ b/analysis/to_pandas.py @@ -0,0 +1,17 @@ +# Convert processor object to pandas dataframe + +import pandas as pd +from .ros_processor import RosProcessor + +def callback_durations_to_df(ros_processor): + callback_addresses = [] + durations = [] + for addr in ros_processor.callbacks_instances: + for d in ros_processor.callbacks_instances[addr]: + callback_addresses.append(addr) + durations.append(d) + + return pd.DataFrame(data={ + 'callback_address': callback_addresses, + 'duration': durations, + }) diff --git a/process.py b/process.py index fa576d1..76d04a5 100644 --- a/process.py +++ b/process.py @@ -3,7 +3,9 @@ import sys import pickle -from tracetools_analysis.analysis.ros import * +import pandas as pd +from tracetools_analysis.analysis.ros_processor import * +from tracetools_analysis.analysis.to_pandas import * def main(argv=sys.argv): if len(argv) != 2: @@ -14,7 +16,11 @@ def main(argv=sys.argv): with open(pickle_filename, 'rb') as f: events = _get_events_from_pickled_file(f) print(f'imported {len(events)} events') - ros_process(events) + processor = ros_process(events) + + df = callback_durations_to_df(processor) + print(df.to_string()) + def _get_events_from_pickled_file(file): p = pickle.Unpickler(file)