ires: Mon, 11 Aug 2036 14:03:04 GMT ETag: "cf7ce8229a6cae61848c735fd0a38cb5748a7dd2" # flamegraph.py - create flame graphs from perf samples # SPDX-License-Identifier: GPL-2.0 # # Usage: # # perf record -a -g -F 99 sleep 60 # perf script report flamegraph # # Combined: # # perf script flamegraph -a -F 99 sleep 60 # # Written by Andreas Gerstmayr # Flame Graphs invented by Brendan Gregg # Works in tandem with d3-flame-graph by Martin Spier # # pylint: disable=missing-module-docstring # pylint: disable=missing-class-docstring # pylint: disable=missing-function-docstring from __future__ import print_function import argparse import hashlib import io import json import os import subprocess import sys import urllib.request minimal_html = """
""" # pylint: disable=too-few-public-methods class Node: def __init__(self, name, libtype): self.name = name # "root" | "kernel" | "" # "" indicates user space self.libtype = libtype self.value = 0 self.children = [] def to_json(self): return { "n": self.name, "l": self.libtype, "v": self.value, "c": self.children } class FlameGraphCLI: def __init__(self, args): self.args = args self.stack = Node("all", "root") @staticmethod def get_libtype_from_dso(dso): """ when kernel-debuginfo is installed, dso points to /usr/lib/debug/lib/modules/*/vmlinux """ if dso and (dso == "[kernel.kallsyms]" or dso.endswith("/vmlinux")): return "kernel" return "" @staticmethod def find_or_create_node(node, name, libtype): for child in node.children: if child.name == name: return child child = Node(name, libtype) node.children.append(child) return child def process_event(self, event): pid = event.get("sample", {}).get("pid", 0) # event["dso"] sometimes contains /usr/lib/debug/lib/modules/*/vmlinux # for user-space processes; let's use pid for kernel or user-space distinction if pid == 0: comm = event["comm"] libtype = "kernel" else: comm = "{} ({})".format(event["comm"], pid) libtype = "" node = self.find_or_create_node(self.stack, comm, libtype) if "callchain" in event: for entry in reversed(event["callchain"]): name = entry.get("sym", {}).get("name", "[unknown]") libtype = self.get_libtype_from_dso(entry.get("dso")) node = self.find_or_create_node(node, name, libtype) else: name = event.get("symbol", "[unknown]") libtype = self.get_libtype_from_dso(event.get("dso")) node = self.find_or_create_node(node, name, libtype) node.value += 1 def get_report_header(self): if self.args.input == "-": # when this script is invoked with "perf script flamegraph",