mirror of
				https://github.com/ARM-software/devlib.git
				synced 2025-11-04 16:01:20 +00:00 
			
		
		
		
	ftrace: add support to report function profiling data
Functions profiling data are reported in a set of files, one for each CPU. This patch adds the required support to collect these data into a single JSON formatted file. Data are collected using a shutils routing on the target side and formatted in JSON on the host side. Signed-off-by: Patrick Bellasi <patrick.bellasi@arm.com>
This commit is contained in:
		@@ -43,6 +43,18 @@ cpufreq_trace_all_frequencies() {
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
# FTrace Utility Functions
 | 
			
		||||
################################################################################
 | 
			
		||||
 | 
			
		||||
ftrace_get_function_stats() {
 | 
			
		||||
    for CPU in $(ls /sys/kernel/debug/tracing/trace_stat | sed 's/function//'); do
 | 
			
		||||
        REPLACE_STRING="s/  Function/\n  Function (CPU$CPU)/"
 | 
			
		||||
        cat /sys/kernel/debug/tracing/trace_stat/function$CPU \
 | 
			
		||||
            | sed "$REPLACE_STRING"
 | 
			
		||||
    done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
# Main Function Dispatcher
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -63,6 +75,9 @@ cpufreq_get_all_governors)
 | 
			
		||||
cpufreq_trace_all_frequencies)
 | 
			
		||||
    cpufreq_trace_all_frequencies $*
 | 
			
		||||
    ;;
 | 
			
		||||
ftrace_get_function_stats)
 | 
			
		||||
    ftrace_get_function_stats
 | 
			
		||||
    ;;
 | 
			
		||||
*)
 | 
			
		||||
    echo "Command [$CMD] not supported"
 | 
			
		||||
    exit -1
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,9 @@
 | 
			
		||||
 | 
			
		||||
from __future__ import division
 | 
			
		||||
import os
 | 
			
		||||
import json
 | 
			
		||||
import time
 | 
			
		||||
import re
 | 
			
		||||
import subprocess
 | 
			
		||||
 | 
			
		||||
from devlib.trace import TraceCollector
 | 
			
		||||
@@ -27,6 +29,7 @@ from devlib.utils.misc import check_output, which
 | 
			
		||||
TRACE_MARKER_START = 'TRACE_MARKER_START'
 | 
			
		||||
TRACE_MARKER_STOP = 'TRACE_MARKER_STOP'
 | 
			
		||||
OUTPUT_TRACE_FILE = 'trace.dat'
 | 
			
		||||
OUTPUT_PROFILE_FILE = 'trace_stat.dat'
 | 
			
		||||
DEFAULT_EVENTS = [
 | 
			
		||||
    'cpu_frequency',
 | 
			
		||||
    'cpu_idle',
 | 
			
		||||
@@ -40,6 +43,9 @@ DEFAULT_EVENTS = [
 | 
			
		||||
]
 | 
			
		||||
TIMEOUT = 180
 | 
			
		||||
 | 
			
		||||
# Regexps for parsing of function profiling data
 | 
			
		||||
CPU_RE = re.compile(r'  Function \(CPU([0-9]+)\)')
 | 
			
		||||
STATS_RE = re.compile(r'([^ ]*) +([0-9]+) +([0-9.]+) us +([0-9.]+) us +([0-9.]+) us')
 | 
			
		||||
 | 
			
		||||
class FtraceCollector(TraceCollector):
 | 
			
		||||
 | 
			
		||||
@@ -165,6 +171,44 @@ class FtraceCollector(TraceCollector):
 | 
			
		||||
            if self.autoview:
 | 
			
		||||
                self.view(outfile)
 | 
			
		||||
 | 
			
		||||
    def get_stats(self, outfile):
 | 
			
		||||
        if not self.functions:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if os.path.isdir(outfile):
 | 
			
		||||
            outfile = os.path.join(outfile, OUTPUT_PROFILE_FILE)
 | 
			
		||||
        output = self.target._execute_util('ftrace_get_function_stats',
 | 
			
		||||
                                            as_root=True)
 | 
			
		||||
 | 
			
		||||
        function_stats = {}
 | 
			
		||||
        for line in output.splitlines():
 | 
			
		||||
            # Match a new CPU dataset
 | 
			
		||||
            match = CPU_RE.search(line)
 | 
			
		||||
            if match:
 | 
			
		||||
                cpu_id = int(match.group(1))
 | 
			
		||||
                function_stats[cpu_id] = {}
 | 
			
		||||
                self.logger.debug("Processing stats for CPU%d...", cpu_id)
 | 
			
		||||
                continue
 | 
			
		||||
            # Match a new function dataset
 | 
			
		||||
            match = STATS_RE.search(line)
 | 
			
		||||
            if match:
 | 
			
		||||
                fname = match.group(1)
 | 
			
		||||
                function_stats[cpu_id][fname] = {
 | 
			
		||||
                        'hits' : int(match.group(2)),
 | 
			
		||||
                        'time' : float(match.group(3)),
 | 
			
		||||
                        'avg'  : float(match.group(4)),
 | 
			
		||||
                        's_2'  : float(match.group(5)),
 | 
			
		||||
                    }
 | 
			
		||||
                self.logger.debug(" %s: %s",
 | 
			
		||||
                             fname, function_stats[cpu_id][fname])
 | 
			
		||||
 | 
			
		||||
        self.logger.debug("FTrace stats output [%s]...", outfile)
 | 
			
		||||
        with open(outfile, 'w') as fh:
 | 
			
		||||
           json.dump(function_stats, fh, indent=4)
 | 
			
		||||
        self.logger.info("FTrace function stats save in [%s]", outfile)
 | 
			
		||||
 | 
			
		||||
        return function_stats
 | 
			
		||||
 | 
			
		||||
    def report(self, binfile, destfile):
 | 
			
		||||
        # To get the output of trace.dat, trace-cmd must be installed
 | 
			
		||||
        # This is done host-side because the generated file is very large
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user