{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Tutorial 12: Flame Charts\n", "\n", "This tutorial demonstrates how to create flame charts using maxplotlib across different backends.\n", "\n", "Flame charts are powerful visualizations for hierarchical profiling data, showing function call stacks and their execution times or sample counts." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from maxplotlib import Canvas" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic Flame Chart\n", "\n", "Let's create a simple flame chart showing a function call hierarchy." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Define function call hierarchy\n", "labels = [\n", " \"main()\", # 0 - root\n", " \"process_data()\", # 1 - child of main\n", " \"load_file()\", # 2 - child of process_data\n", " \"parse_json()\", # 3 - child of process_data\n", " \"validate()\", # 4 - child of process_data\n", "]\n", "\n", "# Parent indices (None for root, index for parent)\n", "parents = [None, 0, 1, 1, 1]\n", "\n", "# Duration or sample count for each function\n", "values = [100, 60, 15, 20, 25]\n", "\n", "# Start times (when each function begins)\n", "start_times = [0, 0, 0, 15, 35]\n", "\n", "# Create canvas and add flame chart\n", "canvas = Canvas(nrows=1, ncols=1, figsize=(12, 6))\n", "canvas.flame_chart(\n", " labels=labels,\n", " parents=parents,\n", " values=values,\n", " start_times=start_times,\n", " colormap=\"viridis\",\n", " edgecolor=\"black\",\n", ")\n", "\n", "canvas.set_xlabel(\"Time (ms)\")\n", "canvas.set_ylabel(\"Stack Depth\")\n", "canvas.set_title(\"Function Call Hierarchy\")\n", "canvas.render(backend=\"matplotlib\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Complex Call Stack\n", "\n", "Visualize a more complex profiling scenario with multiple levels." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# More complex hierarchy\n", "labels = [\n", " \"main()\",\n", " \"init()\",\n", " \"setup_db()\",\n", " \"connect()\",\n", " \"authenticate()\",\n", " \"process()\",\n", " \"fetch_data()\",\n", " \"query_db()\",\n", " \"transform()\",\n", " \"map()\",\n", " \"reduce()\",\n", " \"cleanup()\",\n", "]\n", "\n", "parents = [\n", " None, # main\n", " 0, # init -> main\n", " 1, # setup_db -> init\n", " 2, # connect -> setup_db\n", " 2, # authenticate -> setup_db\n", " 0, # process -> main\n", " 5, # fetch_data -> process\n", " 6, # query_db -> fetch_data\n", " 5, # transform -> process\n", " 8, # map -> transform\n", " 8, # reduce -> transform\n", " 0, # cleanup -> main\n", "]\n", "\n", "values = [200, 40, 30, 15, 15, 120, 50, 40, 70, 35, 35, 20]\n", "start_times = [0, 0, 0, 0, 15, 40, 40, 40, 90, 90, 125, 180]\n", "\n", "canvas = Canvas(nrows=1, ncols=1, figsize=(14, 8))\n", "canvas.flame_chart(\n", " labels=labels,\n", " parents=parents,\n", " values=values,\n", " start_times=start_times,\n", " colormap=\"plasma\",\n", " edgecolor=\"black\",\n", ")\n", "\n", "canvas.set_xlabel(\"Time (ms)\")\n", "canvas.set_ylabel(\"Stack Depth\")\n", "canvas.set_title(\"Complex Application Profiling\")\n", "canvas.render(backend=\"matplotlib\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CPU Profiling Simulation\n", "\n", "Simulate CPU profiling data with multiple parallel execution paths." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Simulate CPU profiling with parallel tasks\n", "labels = [\n", " \"app_main\",\n", " \"worker_1\",\n", " \"compute_heavy\",\n", " \"math_ops\",\n", " \"worker_2\",\n", " \"io_bound\",\n", " \"read_file\",\n", " \"worker_3\",\n", " \"network_call\",\n", " \"http_request\",\n", "]\n", "\n", "parents = [None, 0, 1, 2, 0, 4, 5, 0, 7, 8]\n", "values = [150, 50, 40, 30, 45, 35, 25, 55, 45, 35]\n", "start_times = [0, 0, 0, 5, 50, 50, 55, 95, 95, 100]\n", "\n", "canvas = Canvas(nrows=1, ncols=1, figsize=(12, 6))\n", "canvas.flame_chart(\n", " labels=labels,\n", " parents=parents,\n", " values=values,\n", " start_times=start_times,\n", " colormap=\"inferno\",\n", " edgecolor=\"darkred\",\n", ")\n", "\n", "canvas.set_xlabel(\"Time (ms)\")\n", "canvas.set_ylabel(\"Call Stack Depth\")\n", "canvas.set_title(\"CPU Profiling: Parallel Workers\")\n", "canvas.render(backend=\"matplotlib\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Interactive Flame Chart with Plotly\n", "\n", "Create an interactive version for detailed exploration." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "labels = [\n", " \"main()\",\n", " \"process_data()\",\n", " \"load_file()\",\n", " \"parse_json()\",\n", " \"validate()\",\n", " \"compute()\",\n", " \"algorithm_a()\",\n", " \"algorithm_b()\",\n", " \"save_results()\",\n", "]\n", "\n", "parents = [None, 0, 1, 1, 1, 0, 5, 5, 0]\n", "values = [100, 40, 10, 15, 15, 50, 25, 25, 10]\n", "start_times = [0, 0, 0, 10, 25, 40, 40, 65, 90]\n", "\n", "canvas = Canvas(nrows=1, ncols=1, figsize=(12, 6))\n", "canvas.flame_chart(\n", " labels=labels,\n", " parents=parents,\n", " values=values,\n", " start_times=start_times,\n", " colormap=\"Viridis\",\n", " edgecolor=\"black\",\n", ")\n", "\n", "canvas.set_xlabel(\"Time (ms)\")\n", "canvas.set_ylabel(\"Stack Depth\")\n", "canvas.set_title(\"Interactive Flame Chart - Hover for Details\")\n", "fig = canvas.render(backend=\"plotly\")\n", "fig.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Auto-computed Start Times\n", "\n", "Let maxplotlib compute start times automatically from the hierarchy." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# When start_times=None, they are computed automatically\n", "labels = [\"root\", \"child1\", \"child2\", \"grandchild1\", \"grandchild2\"]\n", "parents = [None, 0, 0, 1, 1]\n", "values = [100, 50, 50, 25, 25]\n", "\n", "canvas = Canvas(nrows=1, ncols=1, figsize=(10, 5))\n", "canvas.flame_chart(\n", " labels=labels,\n", " parents=parents,\n", " values=values,\n", " start_times=None, # Auto-computed\n", " colormap=\"coolwarm\",\n", ")\n", "\n", "canvas.set_xlabel(\"Relative Time\")\n", "canvas.set_ylabel(\"Depth\")\n", "canvas.set_title(\"Flame Chart with Auto-computed Start Times\")\n", "canvas.render(backend=\"matplotlib\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Comparison: Different Colormaps\n", "\n", "Explore different colormap options for flame charts." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "labels = [\"main\", \"func1\", \"func2\", \"func3\", \"func4\"]\n", "parents = [None, 0, 1, 1, 0]\n", "values = [100, 60, 30, 30, 40]\n", "start_times = [0, 0, 0, 30, 60]\n", "\n", "colormaps = [\"viridis\", \"plasma\", \"inferno\", \"magma\"]\n", "\n", "for cmap in colormaps:\n", " canvas = Canvas(nrows=1, ncols=1, figsize=(10, 4))\n", " canvas.flame_chart(\n", " labels=labels,\n", " parents=parents,\n", " values=values,\n", " start_times=start_times,\n", " colormap=cmap,\n", " edgecolor=\"black\",\n", " )\n", " canvas.set_title(f\"Colormap: {cmap}\")\n", " canvas.render(backend=\"matplotlib\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Real-world Example: Web Request Processing\n", "\n", "Visualize the processing of a web request through various layers." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "labels = [\n", " \"handle_request\",\n", " \"authenticate\",\n", " \"check_token\",\n", " \"verify_signature\",\n", " \"route_handler\",\n", " \"validate_input\",\n", " \"business_logic\",\n", " \"db_query\",\n", " \"cache_check\",\n", " \"serialize_response\",\n", " \"json_encode\",\n", " \"send_response\",\n", "]\n", "\n", "parents = [None, 0, 1, 2, 0, 4, 4, 6, 6, 0, 9, 0]\n", "values = [200, 30, 20, 15, 140, 15, 100, 50, 30, 20, 15, 10]\n", "start_times = [0, 0, 5, 10, 30, 30, 45, 45, 95, 170, 170, 190]\n", "\n", "canvas = Canvas(nrows=1, ncols=1, figsize=(14, 7))\n", "canvas.flame_chart(\n", " labels=labels,\n", " parents=parents,\n", " values=values,\n", " start_times=start_times,\n", " colormap=\"RdYlGn_r\",\n", " edgecolor=\"black\",\n", ")\n", "\n", "canvas.set_xlabel(\"Time (ms)\")\n", "canvas.set_ylabel(\"Call Stack\")\n", "canvas.set_title(\"Web Request Processing Profile\")\n", "canvas.render(backend=\"matplotlib\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Summary\n", "\n", "Flame charts in maxplotlib support:\n", "- Hierarchical profiling data visualization\n", "- Automatic depth calculation from parent relationships\n", "- Optional auto-computed start times\n", "- Multiple colormap options\n", "- All backends: matplotlib, plotly, plotext, tikzfigure\n", "- Interactive exploration with plotly backend\n", "- Customizable colors and edge styling\n", "\n", "Perfect for:\n", "- CPU profiling analysis\n", "- Function call stack visualization\n", "- Performance bottleneck identification\n", "- Execution time analysis" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 4 }