From ca1fc0ea50991db564d9b2051bc009c0eb832745 Mon Sep 17 00:00:00 2001 From: Maximilian Schmeller Date: Wed, 15 Feb 2023 17:02:20 +0900 Subject: [PATCH] Adapt to paper requirements --- batch_analyze.py | 2 +- trace-analysis.ipynb | 264 +++++++++++++++++++++---------------------- 2 files changed, 128 insertions(+), 138 deletions(-) diff --git a/batch_analyze.py b/batch_analyze.py index 72e3d1b..976a8a5 100755 --- a/batch_analyze.py +++ b/batch_analyze.py @@ -65,7 +65,7 @@ if __name__ == "__main__": parser = argparse.ArgumentParser() - parser.add_argument('--base-directory', '-d', default=os.path.expandvars('$HOME/Projects/ma-measurements'), + parser.add_argument('--base-directory', '-d', default=os.path.expandvars('$HOME/runner_artifacts'), help='The base directory containing all artifacts directories to be processed') parser.add_argument('--name-filter', '-f', default="artifacts_*", help="A shell-style wildcard expression to filter artifact folder names within the base directory. E.g. 'artifacts_2023*'.") diff --git a/trace-analysis.ipynb b/trace-analysis.ipynb index f0c7c2d..1256ca4 100644 --- a/trace-analysis.ipynb +++ b/trace-analysis.ipynb @@ -3,6 +3,9 @@ { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "import os\n", @@ -21,23 +24,23 @@ "plt.rcParams['figure.dpi'] = 300\n", "\n", "%matplotlib inline" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", - "source": [ - "# User Settings" - ], "metadata": { "collapsed": false - } + }, + "source": [ + "# User Settings" + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "##################################################\n", @@ -56,13 +59,12 @@ "\n", "# The path to the build folder of a ROS2 workspace that contains the\n", "# tracetools_read and tracetools_analysis folders.\n", - "TRACING_WS_BUILD_PATH = \"~/Projects/autoware/build\"\n", + "TRACING_WS_BUILD_PATH = \"/path/to/tracing_ws/build\"\n", "\n", "# Path to trace directory (e.g. ~/.ros/my-trace/ust) or to a converted trace file.\n", "# Using the path \"/ust\" at the end is optional but greatly reduces processing time\n", "# if kernel traces are also present.\n", - "# TR_PATH = \"~/Downloads/iteration1_worker1/aw_replay/tracing/scenario-trace/ust\"\n", - "TR_PATH = \"/home/max/Projects/ma-measurements/artifacts_20221223_155956/tracing/max-ma-trace/ust\"\n", + "TR_PATH = \"/path/to/tracing/session-name/ust\"\n", "\n", "# Path to the folder all artifacts from this notebook are saved to.\n", "# This entails plots as well as data tables.\n", @@ -75,7 +77,7 @@ "BW_ENABLED = False\n", "# Path to a HDF5 file as output by ma-hw-perf-tools/messages/record.bash\n", "# Used to annotate message sizes in E2E latency calculations\n", - "BW_PATH = \"../ma-hw-perf-tools/data/messages-x86.h5\"\n", + "BW_PATH = \"path/to/messages.h5\"\n", "\n", "# Whether to use dependencies extracted by the Clang-tools to supplement\n", "# automatic node-internal data flow annotations.\n", @@ -83,7 +85,7 @@ "CL_ENABLED = False\n", "# Path to the output directory of the ROS2 dependency checker.\n", "# Will only be used if CL_ENABLED is True.\n", - "CL_PATH = \"~/Projects/llvm-project/clang-tools-extra/ros2-internal-dependency-checker/output\"\n", + "CL_PATH = \"/path/to/code_analysis/output\"\n", "\n", "# Whether to compute data flow graphs.\n", "# If you are only interested in E2E latencies, set this to False\n", @@ -209,14 +211,14 @@ " if isinstance(v, Iterable) and not isinstance(v, str):\n", " v = (\"\\n \" + (\" \" * 44)).join(list(map(str, v)))\n", " print(f\" {k:.<40s} := {v}\")" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "# The last few imports can only be resolved using the user-specified paths above\n", @@ -230,25 +232,25 @@ "from tracetools_analysis.processor.ros2 import Ros2Handler\n", "\n", "from tracing_interop.tr_types import *" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "collapsed": false + }, "source": [ "# Load Trace Data\n", "\n", "Load (and, if necessary, convert) tracing data obtained through ros2_tracing. Build indices for fast analysis." - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "def _load_traces():\n", @@ -278,14 +280,14 @@ " globals()[name] = getattr(_tracing_context, name)\n", "\n", "print(\"Done.\")" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "##################################################\n", @@ -320,14 +322,14 @@ "publishers.rebuild()\n", "print(\"Adding new topics and rebuilding topic index\")\n", "topics.append(tf_split_topics)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "print(\"Artificial TF topics (/tf[...]):\")\n", @@ -339,14 +341,14 @@ " #for node in nodes:\n", " # if node.path.startswith(prefix) and node.path.removeprefix(prefix).count(\"/\") <= 1 and \"transform_listener_impl\" not in node.path:\n", " # print(f\" -> {' ' * (len(prefix) - 3)}{node.path.removeprefix(prefix)}\")" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "##################################################\n", @@ -368,24 +370,24 @@ " for f in E2E_OUTPUT_TOPIC_PATTERNS:\n", " if re.search(f, t.name):\n", " print(f\"--[DEBUG] {f:<30s}:{t.name:.<89s} | {sum(map(lambda p: len(p.instances), t.publishers)):>5d} msgs\")" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "collapsed": false + }, "source": [ "# Analyze ROS Graph\n", "Reconstruct namespace hierarchy, data flow graph between callbacks." - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "import latency_graph.latency_graph_structure as lg\n", @@ -396,24 +398,24 @@ "\n", "\n", "lat_graph = cached(\"lat_graph\", _make_latency_graph, [TR_PATH], not CACHING_ENABLED)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "collapsed": false + }, "source": [ "## Plot ROS Graph (full)\n", "Plot the DFG hierarchically by node namespace. Plot each internal and external dependency between callbacks as one arrow." - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "%%skip_if_false DFG_ENABLED\n", @@ -426,24 +428,27 @@ "from latency_graph.latency_graph_plots import plot_latency_graph_full\n", "\n", "plot_latency_graph_full(lat_graph, _tracing_context, os.path.join(OUT_PATH, \"latency_graph_full\"))" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "collapsed": false + }, "source": [ "## Plot Latency Graph (overview)\n", "Plot the DFG down to a certain hierarchy level in a flattened manner. Aggregate dependencies from multiple callbacks into corresponding node-node dependencies." - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%%%skip_if_false DFG_ENABLED\n" + } + }, "outputs": [], "source": [ "%%skip_if_false DFG_ENABLED\n", @@ -457,27 +462,24 @@ "from latency_graph.latency_graph_plots import plot_latency_graph_overview\n", "\n", "plot_latency_graph_overview(lat_graph, DFG_EXCL_NODE_PATTERNS, DFG_INPUT_NODE_PATTERNS, DFG_OUTPUT_NODE_PATTERNS, DFG_MAX_HIER_LEVEL, os.path.join(OUT_PATH, \"latency_graph_overview\"))" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%%%skip_if_false DFG_ENABLED\n" - } - } + ] }, { "cell_type": "markdown", + "metadata": { + "collapsed": false + }, "source": [ "# Analyze Message Flow\n", "Build dependency trees ending in the specified output topics." - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "%%skip_if_false E2E_ENABLED\n", @@ -495,14 +497,14 @@ " import traceback\n", " print(e)\n", " traceback.print_exc()" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "%%skip_if_false E2E_ENABLED\n", @@ -518,14 +520,14 @@ "\n", "from bw_interop.bw_plots import dds_lat_msg_size_scatter\n", "plot_topic = \"\"" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "%%skip_if_false E2E_ENABLED\n", @@ -540,14 +542,14 @@ "trees_paths = [e2e_paths_sorted_desc(tree, E2E_INPUT_TOPIC_PATTERNS) for tree in tqdm(trees, mininterval=10.0,\n", " desc=\"Extracting E2E paths\")]\n", "all_paths = [p for paths in trees_paths for p in paths]" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "%%skip_if_false E2E_ENABLED\n", @@ -575,14 +577,14 @@ "df_print = df_print.sort_values((\"e2e_latency\", \"count\"), ascending=False)\n", "df_print.to_csv(os.path.join(OUT_PATH, \"e2e_overview.csv\"), sep=\"\\t\", index=False)\n", "df_print" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "import pickle\n", @@ -590,14 +592,14 @@ "# pickle.dump((trees_paths, all_paths, cohorts), f)\n", "with open(os.path.join(OUT_PATH, \"state.pkl\"), \"wb\") as f:\n", " pickle.dump((trees_paths, all_paths, cohorts), f)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "##################################################\n", @@ -623,14 +625,14 @@ " print(f\"[WARN] Expected exactly one cohort to remain, got {len(cohorts_filt)}. Only the first one will be used.\")\n", "\n", "relevant_path, relevant_dataflows = next(iter(cohorts_filt.items()))" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "from message_tree.message_tree_algorithms import e2e_latency_breakdown\n", @@ -650,14 +652,14 @@ "#e2e_breakdowns_orig = e2e_breakdowns\n", "\n", "#relevant_dataflows, e2e_breakdowns = zip(*filt)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "%%skip_if_false E2E_ENABLED\n", @@ -713,14 +715,14 @@ "plt.savefig(os.path.join(OUT_PATH, \"plot_e2e_portions.png\"))\n", "\n", "None\n" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "%%skip_if_false E2E_ENABLED\n", @@ -747,14 +749,14 @@ "ax.text(np.mean(e2es) * 1.02, max_ylim * 0.98, 'Mean: {:.3f}s'.format(np.mean(e2es)))\n", "plt.savefig(os.path.join(OUT_PATH, \"plot_e2es.png\"))\n", "None" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "%%skip_if_false E2E_ENABLED\n", @@ -806,14 +808,14 @@ "df_types.to_csv(os.path.join(OUT_PATH, \"plot_e2es_violin_types.csv\"), index=False, header=[\"type\"])\n", "\n", "None" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "for concat_pc_items in component_latency_items:\n", @@ -822,14 +824,14 @@ " dur_ts_records = [(item.location[0].timestamp, item.duration) for item in concat_pc_items]\n", " df_dur_ts = pd.DataFrame(dur_ts_records, columns=(\"timestamp\", \"duration\"))\n", " df_dur_ts.to_csv(os.path.join(OUT_PATH, f\"dur_ts_{concat_pc_items[0].location[0].publisher.topic_name.replace('/', '__')}.csv\"), index=False)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "indices = [i for i, t in enumerate(types) if t == \"cpu\"]\n", @@ -839,14 +841,14 @@ "records = [(lbl, x.mean(), x.std(), x.min(), x.max()) for x, lbl in zip(xs, lbls)]\n", "df_cpu = pd.DataFrame(records, columns=[\"callback\", \"mean\", \"std\", \"min\", \"max\"])\n", "df_cpu.to_csv(os.path.join(OUT_PATH, \"calc_times.csv\"), index=False)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "%%skip_if_false E2E_ENABLED\n", @@ -858,30 +860,18 @@ "fig.set_size_inches(16, 9)\n", "fig.set_dpi(300)\n", "None" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "print(\"Done.\")" - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": null, - "outputs": [], - "source": [], - "metadata": { - "collapsed": false - } + ] } ], "metadata": {