Commit 258dfd41 authored by Anup Sharma's avatar Anup Sharma Committed by Arnaldo Carvalho de Melo

perf scripts python: Implement add sample function and thread processing

The intern_stack function is responsible for retrieving
or creating a stack_id based on the provided frame_id and prefix_id.
It first generates a key using the frame_id and prefix_id values.
If the stack corresponding to the key is found in the stackMap,
it is returned. Otherwise, a new stack is created by appending
the prefix_id and frame_id to the stackTable. The key
and the index of the newly created stack are added to the
stackMap for future reference.

The _intern_frame function is responsible for retrieving or
creating a frame_id based on the provided frame string. If the frame_id
corresponding to the frameString is found in the frameMap, it is
returned. Otherwise, a new frame is created by appending relevant
information to the frameTable and adding the frameString to the string_id
through _intern_string.

The _intern_string function will gets a matching string, or saves the new
string and returns a String ID.
Signed-off-by: default avatarAnup Sharma <anupnewsmail@gmail.com>
Link: https://lore.kernel.org/r/4442f4b1ab4c7317cf940560a3a285fcdfbeeb08.1689961706.git.anupnewsmail@gmail.com
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: linux-kernel@vger.kernel.org
Cc: linux-perf-users@vger.kernel.org
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 833daec7
...@@ -13,6 +13,7 @@ import os ...@@ -13,6 +13,7 @@ import os
import sys import sys
import json import json
import argparse import argparse
from functools import reduce
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import List, Dict, Optional, NamedTuple, Set, Tuple, Any from typing import List, Dict, Optional, NamedTuple, Set, Tuple, Any
...@@ -39,6 +40,10 @@ CATEGORIES = None ...@@ -39,6 +40,10 @@ CATEGORIES = None
# The product name is used by the profiler UI to show the Operating system and Processor. # The product name is used by the profiler UI to show the Operating system and Processor.
PRODUCT = os.popen('uname -op').read().strip() PRODUCT = os.popen('uname -op').read().strip()
# The category index is used by the profiler UI to show the color of the flame graph.
USER_CATEGORY_INDEX = 0
KERNEL_CATEGORY_INDEX = 1
# https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L156 # https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L156
class Frame(NamedTuple): class Frame(NamedTuple):
string_id: StringID string_id: StringID
...@@ -99,6 +104,55 @@ class Thread: ...@@ -99,6 +104,55 @@ class Thread:
stackMap: Dict[Tuple[Optional[int], int], int] = field(default_factory=dict) stackMap: Dict[Tuple[Optional[int], int], int] = field(default_factory=dict)
frameMap: Dict[str, int] = field(default_factory=dict) frameMap: Dict[str, int] = field(default_factory=dict)
def _intern_stack(self, frame_id: int, prefix_id: Optional[int]) -> int:
"""Gets a matching stack, or saves the new stack. Returns a Stack ID."""
key = f"{frame_id}" if prefix_id is None else f"{frame_id},{prefix_id}"
# key = (prefix_id, frame_id)
stack_id = self.stackMap.get(key)
if stack_id is None:
# return stack_id
stack_id = len(self.stackTable)
self.stackTable.append(Stack(prefix_id=prefix_id, frame_id=frame_id))
self.stackMap[key] = stack_id
return stack_id
def _intern_string(self, string: str) -> int:
"""Gets a matching string, or saves the new string. Returns a String ID."""
string_id = self.stringMap.get(string)
if string_id is not None:
return string_id
string_id = len(self.stringTable)
self.stringTable.append(string)
self.stringMap[string] = string_id
return string_id
def _intern_frame(self, frame_str: str) -> int:
"""Gets a matching stack frame, or saves the new frame. Returns a Frame ID."""
frame_id = self.frameMap.get(frame_str)
if frame_id is not None:
return frame_id
frame_id = len(self.frameTable)
self.frameMap[frame_str] = frame_id
string_id = self._intern_string(frame_str)
symbol_name_to_category = KERNEL_CATEGORY_INDEX if frame_str.find('kallsyms') != -1 \
or frame_str.find('/vmlinux') != -1 \
or frame_str.endswith('.ko)') \
else USER_CATEGORY_INDEX
self.frameTable.append(Frame(
string_id=string_id,
relevantForJS=False,
innerWindowID=0,
implementation=None,
optimizations=None,
line=None,
column=None,
category=symbol_name_to_category,
subcategory=None,
))
return frame_id
def _to_json_dict(self) -> Dict: def _to_json_dict(self) -> Dict:
"""Converts current Thread to GeckoThread JSON format.""" """Converts current Thread to GeckoThread JSON format."""
# Gecko profile format is row-oriented data as List[List], # Gecko profile format is row-oriented data as List[List],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment