* [PATCH v5 0/8] Add support for Firefox's gecko profile format
@ 2023-07-21 17:51 Anup Sharma
2023-07-21 17:52 ` [PATCH v5 1/8] perf scripts python: Add initial script file with usage information Anup Sharma
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Anup Sharma @ 2023-07-21 17:51 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
Ian Rogers, Adrian Hunter, Anup Sharma, linux-perf-users,
linux-kernel
This patch series adds support for Firefox's gecko profile format.
The format is documented here [1].
I have incorporated several changes based on feedback from the
previous version of the patch.
Changes in v5:
- Reorganized the patch series to ensure that each patch works independently.
- Renamed the file to perf-gecko.py.
- Added command exection support for the script. The script can now be
executed as "perf script report perf-gecko > output.json."
- Simplified the usage information; previously it was "perf script
perf-gecko.py > output.json," now it is "perf script report
perf-gecko > output.json."
- Merged the test and command execution patches into this series,
which were previously in a separate series.
Committer Testing:
- Tested with a perf.data file generated for single and multiple cpu
cores enabled.
- Uploaded the stdout into profiler.firefox.com and verified the
output.
- Verified the output with the output generated by the existing
script as mentioned here [2].
Method:
- perf record -F 99 -a -g -- sleep 5
- perf script report perf-gecko > output.json
- upload output.json to profiler.firefox.com
[1] https://github.com/firefox-devtools/profiler/blob/main/docs-developer/gecko-profile-format.md
[2] https://perf.wiki.kernel.org/index.php/Tutorial#Firefox_Profiler
Anup Sharma (8):
perf scripts python: Add initial script file with usage information
perf scripts python: Extact necessary information from process event
perf scripts python: Add classes and conversion functions
perf scripts python: Add trace end processing and PRODUCT and
CATEGORIES information
perf scripts python: Implement add sample function and thread
processing
perf scripts python: Implement add sample function and thread
processing
perf scripts python: Add command execution for firefox gecko converter
script
perf test: Add support for testing firefox gecko converter script
.../perf/scripts/python/bin/perf-gecko-record | 2 +
.../perf/scripts/python/bin/perf-gecko-report | 3 +
tools/perf/scripts/python/perf-gecko.py | 339 ++++++++++++++++++
tools/perf/tests/shell/test_perf_gecko.sh | 188 ++++++++++
4 files changed, 532 insertions(+)
create mode 100644 tools/perf/scripts/python/bin/perf-gecko-record
create mode 100644 tools/perf/scripts/python/bin/perf-gecko-report
create mode 100644 tools/perf/scripts/python/perf-gecko.py
create mode 100755 tools/perf/tests/shell/test_perf_gecko.sh
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v5 1/8] perf scripts python: Add initial script file with usage information
2023-07-21 17:51 [PATCH v5 0/8] Add support for Firefox's gecko profile format Anup Sharma
@ 2023-07-21 17:52 ` Anup Sharma
2023-07-21 17:52 ` [PATCH v5 2/8] perf scripts python: Extact necessary information from process event Anup Sharma
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Anup Sharma @ 2023-07-21 17:52 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
Ian Rogers, Adrian Hunter, Anup Sharma, linux-perf-users,
linux-kernel
Added necessary modules, including the Perf-Trace-Util
library, and defines the required functions and variables
for using perf script python. The perf_trace_context and
Core modules for tracing and processing events has been
also imported. Added usage information.
Signed-off-by: Anup Sharma <anupnewsmail@gmail.com>
---
tools/perf/scripts/python/perf-gecko.py | 31 +++++++++++++++++++++++++
1 file changed, 31 insertions(+)
create mode 100644 tools/perf/scripts/python/perf-gecko.py
diff --git a/tools/perf/scripts/python/perf-gecko.py b/tools/perf/scripts/python/perf-gecko.py
new file mode 100644
index 000000000000..4e651adb6395
--- /dev/null
+++ b/tools/perf/scripts/python/perf-gecko.py
@@ -0,0 +1,31 @@
+# firefox-gecko-converter.py - Convert perf record output to Firefox's gecko profile format
+# SPDX-License-Identifier: GPL-2.0
+#
+# The script converts perf.data to Gecko Profile Format,
+# which can be read by https://profiler.firefox.com/.
+#
+# Usage:
+#
+# perf record -a -g -F 99 sleep 60
+# perf script report perf-gecko > output.json
+
+import os
+import sys
+from typing import Dict
+
+# Add the Perf-Trace-Util library to the Python path
+sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+ '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
+
+from perf_trace_context import *
+from Core import *
+
+# Uses perf script python interface to parse each
+# event and store the data in the thread builder.
+def process_event(param_dict: Dict) -> None:
+ pass
+
+# Trace_end runs at the end and will be used to aggregate
+# the data into the final json object and print it out to stdout.
+def trace_end() -> None:
+ pass
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v5 2/8] perf scripts python: Extact necessary information from process event
2023-07-21 17:51 [PATCH v5 0/8] Add support for Firefox's gecko profile format Anup Sharma
2023-07-21 17:52 ` [PATCH v5 1/8] perf scripts python: Add initial script file with usage information Anup Sharma
@ 2023-07-21 17:52 ` Anup Sharma
2023-07-21 17:53 ` [PATCH v5 3/8] perf scripts python: Add classes and conversion functions Anup Sharma
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Anup Sharma @ 2023-07-21 17:52 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
Ian Rogers, Adrian Hunter, Anup Sharma, linux-perf-users,
linux-kernel
The script takes in a sample event dictionary(param_dict) and retrieves
relevant data such as time stamp, PID, TID, and comm for each event.
Also start time is defined as a global variable as it need to be passed
to trace_end for gecko meta information field creation.
Signed-off-by: Anup Sharma <anupnewsmail@gmail.com>
---
tools/perf/scripts/python/perf-gecko.py | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/tools/perf/scripts/python/perf-gecko.py b/tools/perf/scripts/python/perf-gecko.py
index 4e651adb6395..02849d3c9e81 100644
--- a/tools/perf/scripts/python/perf-gecko.py
+++ b/tools/perf/scripts/python/perf-gecko.py
@@ -20,10 +20,22 @@ sys.path.append(os.environ['PERF_EXEC_PATH'] + \
from perf_trace_context import *
from Core import *
+# start_time is intialiazed only once for the all event traces.
+start_time = None
+
# Uses perf script python interface to parse each
# event and store the data in the thread builder.
def process_event(param_dict: Dict) -> None:
- pass
+ global start_time
+ global tid_to_thread
+ time_stamp = (param_dict['sample']['time'] // 1000) / 1000
+ pid = param_dict['sample']['pid']
+ tid = param_dict['sample']['tid']
+ comm = param_dict['comm']
+
+ # Start time is the time of the first sample
+ if not start_time:
+ start_time = time_stamp
# Trace_end runs at the end and will be used to aggregate
# the data into the final json object and print it out to stdout.
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v5 3/8] perf scripts python: Add classes and conversion functions
2023-07-21 17:51 [PATCH v5 0/8] Add support for Firefox's gecko profile format Anup Sharma
2023-07-21 17:52 ` [PATCH v5 1/8] perf scripts python: Add initial script file with usage information Anup Sharma
2023-07-21 17:52 ` [PATCH v5 2/8] perf scripts python: Extact necessary information from process event Anup Sharma
@ 2023-07-21 17:53 ` Anup Sharma
2023-07-21 17:54 ` [PATCH v5 4/8] perf scripts python: Add trace end processing and PRODUCT and CATEGORIES information Anup Sharma
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Anup Sharma @ 2023-07-21 17:53 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
Ian Rogers, Adrian Hunter, Anup Sharma, linux-perf-users,
linux-kernel
This commit introduces new classes and conversion functions to
facilitate the representation of Gecko profile information. The new
classes Frame, Stack, Sample, and Thread are added to handle specific
components of the profile data, also link to the origin docs has been
commented out.
Additionally, Inside the Thread class _to_json_dict() method has been
created that converts the current thread data into the corresponding
format expected by the GeckoThread JSON schema, as per the Gecko
profile format specification.
Signed-off-by: Anup Sharma <anupnewsmail@gmail.com>
---
tools/perf/scripts/python/perf-gecko.py | 133 +++++++++++++++++++++++-
1 file changed, 132 insertions(+), 1 deletion(-)
diff --git a/tools/perf/scripts/python/perf-gecko.py b/tools/perf/scripts/python/perf-gecko.py
index 02849d3c9e81..71e2b042e695 100644
--- a/tools/perf/scripts/python/perf-gecko.py
+++ b/tools/perf/scripts/python/perf-gecko.py
@@ -11,7 +11,8 @@
import os
import sys
-from typing import Dict
+from dataclasses import dataclass, field
+from typing import List, Dict, Optional, NamedTuple, Set, Tuple, Any
# Add the Perf-Trace-Util library to the Python path
sys.path.append(os.environ['PERF_EXEC_PATH'] + \
@@ -20,9 +21,139 @@ sys.path.append(os.environ['PERF_EXEC_PATH'] + \
from perf_trace_context import *
from Core import *
+StringID = int
+StackID = int
+FrameID = int
+CategoryID = int
+Milliseconds = float
+
# start_time is intialiazed only once for the all event traces.
start_time = None
+# https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L156
+class Frame(NamedTuple):
+ string_id: StringID
+ relevantForJS: bool
+ innerWindowID: int
+ implementation: None
+ optimizations: None
+ line: None
+ column: None
+ category: CategoryID
+ subcategory: int
+
+# https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L216
+class Stack(NamedTuple):
+ prefix_id: Optional[StackID]
+ frame_id: FrameID
+
+# https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L90
+class Sample(NamedTuple):
+ stack_id: Optional[StackID]
+ time_ms: Milliseconds
+ responsiveness: int
+
+@dataclass
+class Thread:
+ """A builder for a profile of the thread.
+
+ Attributes:
+ comm: Thread command-line (name).
+ pid: process ID of containing process.
+ tid: thread ID.
+ samples: Timeline of profile samples.
+ frameTable: interned stack frame ID -> stack frame.
+ stringTable: interned string ID -> string.
+ stringMap: interned string -> string ID.
+ stackTable: interned stack ID -> stack.
+ stackMap: (stack prefix ID, leaf stack frame ID) -> interned Stack ID.
+ frameMap: Stack Frame string -> interned Frame ID.
+ comm: str
+ pid: int
+ tid: int
+ samples: List[Sample] = field(default_factory=list)
+ frameTable: List[Frame] = field(default_factory=list)
+ stringTable: List[str] = field(default_factory=list)
+ stringMap: Dict[str, int] = field(default_factory=dict)
+ stackTable: List[Stack] = field(default_factory=list)
+ stackMap: Dict[Tuple[Optional[int], int], int] = field(default_factory=dict)
+ frameMap: Dict[str, int] = field(default_factory=dict)
+ """
+ comm: str
+ pid: int
+ tid: int
+ samples: List[Sample] = field(default_factory=list)
+ frameTable: List[Frame] = field(default_factory=list)
+ stringTable: List[str] = field(default_factory=list)
+ stringMap: Dict[str, int] = field(default_factory=dict)
+ stackTable: List[Stack] = field(default_factory=list)
+ stackMap: Dict[Tuple[Optional[int], int], int] = field(default_factory=dict)
+ frameMap: Dict[str, int] = field(default_factory=dict)
+
+ def _to_json_dict(self) -> Dict:
+ """Converts current Thread to GeckoThread JSON format."""
+ # Gecko profile format is row-oriented data as List[List],
+ # And a schema for interpreting each index.
+ # Schema:
+ # https://github.com/firefox-devtools/profiler/blob/main/docs-developer/gecko-profile-format.md
+ # https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L230
+ return {
+ "tid": self.tid,
+ "pid": self.pid,
+ "name": self.comm,
+ # https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L51
+ "markers": {
+ "schema": {
+ "name": 0,
+ "startTime": 1,
+ "endTime": 2,
+ "phase": 3,
+ "category": 4,
+ "data": 5,
+ },
+ "data": [],
+ },
+
+ # https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L90
+ "samples": {
+ "schema": {
+ "stack": 0,
+ "time": 1,
+ "responsiveness": 2,
+ },
+ "data": self.samples
+ },
+
+ # https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L156
+ "frameTable": {
+ "schema": {
+ "location": 0,
+ "relevantForJS": 1,
+ "innerWindowID": 2,
+ "implementation": 3,
+ "optimizations": 4,
+ "line": 5,
+ "column": 6,
+ "category": 7,
+ "subcategory": 8,
+ },
+ "data": self.frameTable,
+ },
+
+ # https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L216
+ "stackTable": {
+ "schema": {
+ "prefix": 0,
+ "frame": 1,
+ },
+ "data": self.stackTable,
+ },
+ "stringTable": self.stringTable,
+ "registerTime": 0,
+ "unregisterTime": None,
+ "processType": "default",
+ }
+
# Uses perf script python interface to parse each
# event and store the data in the thread builder.
def process_event(param_dict: Dict) -> None:
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v5 4/8] perf scripts python: Add trace end processing and PRODUCT and CATEGORIES information
2023-07-21 17:51 [PATCH v5 0/8] Add support for Firefox's gecko profile format Anup Sharma
` (2 preceding siblings ...)
2023-07-21 17:53 ` [PATCH v5 3/8] perf scripts python: Add classes and conversion functions Anup Sharma
@ 2023-07-21 17:54 ` Anup Sharma
2023-07-21 17:55 ` [PATCH v5 5/8] perf scripts python: Implement add sample function and thread processing Anup Sharma
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Anup Sharma @ 2023-07-21 17:54 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
Ian Rogers, Adrian Hunter, Anup Sharma, linux-perf-users,
linux-kernel
The final output will now be presented in JSON format following the Gecko
profile structure. Additionally, the inclusion of PRODUCT allows easy retrieval
of header information for UI.
Furthermore, CATEGORIES have been introduced to enable customization of
kernel and user colors using input arguments. To facilitate this functionality,
an argparse-based parser has been implemented.
Note: The implementation of threads will be addressed in subsequent commits
for now I have commented it out.
Signed-off-by: Anup Sharma <anupnewsmail@gmail.com>
---
tools/perf/scripts/python/perf-gecko.py | 65 ++++++++++++++++++++++++-
1 file changed, 64 insertions(+), 1 deletion(-)
diff --git a/tools/perf/scripts/python/perf-gecko.py b/tools/perf/scripts/python/perf-gecko.py
index 71e2b042e695..f0d29f48467e 100644
--- a/tools/perf/scripts/python/perf-gecko.py
+++ b/tools/perf/scripts/python/perf-gecko.py
@@ -11,6 +11,8 @@
import os
import sys
+import json
+import argparse
from dataclasses import dataclass, field
from typing import List, Dict, Optional, NamedTuple, Set, Tuple, Any
@@ -30,6 +32,13 @@ Milliseconds = float
# start_time is intialiazed only once for the all event traces.
start_time = None
+# https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/profile.js#L425
+# Follow Brendan Gregg's Flamegraph convention: orange for kernel and yellow for user space by default.
+CATEGORIES = None
+
+# The product name is used by the profiler UI to show the Operating system and Processor.
+PRODUCT = os.popen('uname -op').read().strip()
+
# https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L156
class Frame(NamedTuple):
string_id: StringID
@@ -171,4 +180,58 @@ def process_event(param_dict: Dict) -> None:
# Trace_end runs at the end and will be used to aggregate
# the data into the final json object and print it out to stdout.
def trace_end() -> None:
- pass
+ # Schema: https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L305
+ gecko_profile_with_meta = {
+ "meta": {
+ "interval": 1,
+ "processType": 0,
+ "product": PRODUCT,
+ "stackwalk": 1,
+ "debug": 0,
+ "gcpoison": 0,
+ "asyncstack": 1,
+ "startTime": start_time,
+ "shutdownTime": None,
+ "version": 24,
+ "presymbolicated": True,
+ "categories": CATEGORIES,
+ "markerSchema": [],
+ },
+ "libs": [],
+ # threads will be implemented in later commits.
+ # "threads": threads,
+ "processes": [],
+ "pausedRanges": [],
+ }
+ json.dump(gecko_profile_with_meta, sys.stdout, indent=2)
+
+def main() -> None:
+ global CATEGORIES
+ parser = argparse.ArgumentParser(description="Convert perf.data to Firefox\'s Gecko Profile format")
+
+ # Add the command-line options
+ # Colors must be defined according to this:
+ # https://github.com/firefox-devtools/profiler/blob/50124adbfa488adba6e2674a8f2618cf34b59cd2/res/css/categories.css
+ parser.add_argument('--user-color', default='yellow', help='Color for the User category')
+ parser.add_argument('--kernel-color', default='orange', help='Color for the Kernel category')
+ # Parse the command-line arguments
+ args = parser.parse_args()
+ # Access the values provided by the user
+ user_color = args.user_color
+ kernel_color = args.kernel_color
+
+ CATEGORIES = [
+ {
+ "name": 'User',
+ "color": user_color,
+ "subcategories": ['Other']
+ },
+ {
+ "name": 'Kernel',
+ "color": kernel_color,
+ "subcategories": ['Other']
+ },
+ ]
+
+if __name__ == '__main__':
+ main()
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v5 5/8] perf scripts python: Implement add sample function and thread processing
2023-07-21 17:51 [PATCH v5 0/8] Add support for Firefox's gecko profile format Anup Sharma
` (3 preceding siblings ...)
2023-07-21 17:54 ` [PATCH v5 4/8] perf scripts python: Add trace end processing and PRODUCT and CATEGORIES information Anup Sharma
@ 2023-07-21 17:55 ` Anup Sharma
2023-07-21 17:56 ` [PATCH v5 6/8] " Anup Sharma
2023-07-21 17:57 ` [PATCH v5 7/8] perf scripts python: Add command execution for perf gecko script Anup Sharma
6 siblings, 0 replies; 9+ messages in thread
From: Anup Sharma @ 2023-07-21 17:55 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
Ian Rogers, Adrian Hunter, Anup Sharma, linux-perf-users,
linux-kernel
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: Anup Sharma <anupnewsmail@gmail.com>
---
tools/perf/scripts/python/perf-gecko.py | 54 +++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/tools/perf/scripts/python/perf-gecko.py b/tools/perf/scripts/python/perf-gecko.py
index f0d29f48467e..35e25e64d6d9 100644
--- a/tools/perf/scripts/python/perf-gecko.py
+++ b/tools/perf/scripts/python/perf-gecko.py
@@ -13,6 +13,7 @@ import os
import sys
import json
import argparse
+from functools import reduce
from dataclasses import dataclass, field
from typing import List, Dict, Optional, NamedTuple, Set, Tuple, Any
@@ -39,6 +40,10 @@ CATEGORIES = None
# The product name is used by the profiler UI to show the Operating system and Processor.
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
class Frame(NamedTuple):
string_id: StringID
@@ -99,6 +104,55 @@ class Thread:
stackMap: Dict[Tuple[Optional[int], int], 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:
"""Converts current Thread to GeckoThread JSON format."""
# Gecko profile format is row-oriented data as List[List],
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v5 6/8] perf scripts python: Implement add sample function and thread processing
2023-07-21 17:51 [PATCH v5 0/8] Add support for Firefox's gecko profile format Anup Sharma
` (4 preceding siblings ...)
2023-07-21 17:55 ` [PATCH v5 5/8] perf scripts python: Implement add sample function and thread processing Anup Sharma
@ 2023-07-21 17:56 ` Anup Sharma
2023-07-21 17:57 ` [PATCH v5 7/8] perf scripts python: Add command execution for perf gecko script Anup Sharma
6 siblings, 0 replies; 9+ messages in thread
From: Anup Sharma @ 2023-07-21 17:56 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
Ian Rogers, Adrian Hunter, Anup Sharma, linux-perf-users,
linux-kernel
The stack has been created for storing func and dso from the callchain.
The sample has been added to a specific thread. It first checks if the
thread exists in the Thread class. Then it call _add_sample function
which is responsible for appending a new entry to the samples list.
Also callchain parsing and storing part is implemented. Moreover removed
the comment from thread.
Signed-off-by: Anup Sharma <anupnewsmail@gmail.com>
---
tools/perf/scripts/python/perf-gecko.py | 52 ++++++++++++++++++++++++-
1 file changed, 50 insertions(+), 2 deletions(-)
diff --git a/tools/perf/scripts/python/perf-gecko.py b/tools/perf/scripts/python/perf-gecko.py
index 35e25e64d6d9..29d10985e176 100644
--- a/tools/perf/scripts/python/perf-gecko.py
+++ b/tools/perf/scripts/python/perf-gecko.py
@@ -40,6 +40,9 @@ CATEGORIES = None
# The product name is used by the profiler UI to show the Operating system and Processor.
PRODUCT = os.popen('uname -op').read().strip()
+# Here key = tid, value = Thread
+tid_to_thread = dict()
+
# 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
@@ -153,6 +156,25 @@ class Thread:
))
return frame_id
+ def _add_sample(self, comm: str, stack: List[str], time_ms: Milliseconds) -> None:
+ """Add a timestamped stack trace sample to the thread builder.
+ Args:
+ comm: command-line (name) of the thread at this sample
+ stack: sampled stack frames. Root first, leaf last.
+ time_ms: timestamp of sample in milliseconds.
+ """
+ # Ihreads may not set their names right after they are created.
+ # Instead, they might do it later. In such situations, to use the latest name they have set.
+ if self.comm != comm:
+ self.comm = comm
+
+ prefix_stack_id = reduce(lambda prefix_id, frame: self._intern_stack
+ (self._intern_frame(frame), prefix_id), stack, None)
+ if prefix_stack_id is not None:
+ self.samples.append(Sample(stack_id=prefix_stack_id,
+ time_ms=time_ms,
+ responsiveness=0))
+
def _to_json_dict(self) -> Dict:
"""Converts current Thread to GeckoThread JSON format."""
# Gecko profile format is row-oriented data as List[List],
@@ -231,9 +253,36 @@ def process_event(param_dict: Dict) -> None:
if not start_time:
start_time = time_stamp
+ # Parse and append the callchain of the current sample into a stack.
+ stack = []
+ if param_dict['callchain']:
+ for call in param_dict['callchain']:
+ if 'sym' not in call:
+ continue
+ stack.append(f'{call["sym"]["name"]} (in {call["dso"]})')
+ if len(stack) != 0:
+ # Reverse the stack, as root come first and the leaf at the end.
+ stack = stack[::-1]
+
+ # During perf record if -g is not used, the callchain is not available.
+ # In that case, the symbol and dso are available in the event parameters.
+ else:
+ func = param_dict['symbol'] if 'symbol' in param_dict else '[unknown]'
+ dso = param_dict['dso'] if 'dso' in param_dict else '[unknown]'
+ stack.append(f'{func} (in {dso})')
+
+ # Add sample to the specific thread.
+ thread = tid_to_thread.get(tid)
+ if thread is None:
+ thread = Thread(comm=comm, pid=pid, tid=tid)
+ tid_to_thread[tid] = thread
+ thread._add_sample(comm=comm, stack=stack, time_ms=time_stamp)
+
# Trace_end runs at the end and will be used to aggregate
# the data into the final json object and print it out to stdout.
def trace_end() -> None:
+ threads = [thread._to_json_dict() for thread in tid_to_thread.values()]
+
# Schema: https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L305
gecko_profile_with_meta = {
"meta": {
@@ -252,8 +301,7 @@ def trace_end() -> None:
"markerSchema": [],
},
"libs": [],
- # threads will be implemented in later commits.
- # "threads": threads,
+ "threads": threads,
"processes": [],
"pausedRanges": [],
}
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v5 7/8] perf scripts python: Add command execution for perf gecko script
2023-07-21 17:51 [PATCH v5 0/8] Add support for Firefox's gecko profile format Anup Sharma
` (5 preceding siblings ...)
2023-07-21 17:56 ` [PATCH v5 6/8] " Anup Sharma
@ 2023-07-21 17:57 ` Anup Sharma
2023-07-27 11:50 ` Arnaldo Carvalho de Melo
6 siblings, 1 reply; 9+ messages in thread
From: Anup Sharma @ 2023-07-21 17:57 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
Ian Rogers, Adrian Hunter, Anup Sharma, linux-perf-users,
linux-kernel
This will enable the execution of perf-gecko.py script
using record and report commands in perf script.
And this will be also reflected at "perf script -l" command.
For Example:
perf script record perf-gecko
perf script report perf-gecko
Signed-off-by: Anup Sharma <anupnewsmail@gmail.com>
---
tools/perf/scripts/python/bin/perf-gecko-record | 2 ++
tools/perf/scripts/python/bin/perf-gecko-report | 3 +++
2 files changed, 5 insertions(+)
create mode 100644 tools/perf/scripts/python/bin/perf-gecko-record
create mode 100644 tools/perf/scripts/python/bin/perf-gecko-report
diff --git a/tools/perf/scripts/python/bin/perf-gecko-record b/tools/perf/scripts/python/bin/perf-gecko-record
new file mode 100644
index 000000000000..7df5a19c0163
--- /dev/null
+++ b/tools/perf/scripts/python/bin/perf-gecko-record
@@ -0,0 +1,2 @@
+#!/bin/bash
+perf record -g "$@"
diff --git a/tools/perf/scripts/python/bin/perf-gecko-report b/tools/perf/scripts/python/bin/perf-gecko-report
new file mode 100644
index 000000000000..6781313dc862
--- /dev/null
+++ b/tools/perf/scripts/python/bin/perf-gecko-report
@@ -0,0 +1,3 @@
+#!/bin/bash
+# description: create firefox gecko profile json format from perf.data
+perf script -s "$PERF_EXEC_PATH"/scripts/python/perf-gecko.py -- "$@"
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v5 7/8] perf scripts python: Add command execution for perf gecko script
2023-07-21 17:57 ` [PATCH v5 7/8] perf scripts python: Add command execution for perf gecko script Anup Sharma
@ 2023-07-27 11:50 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 9+ messages in thread
From: Arnaldo Carvalho de Melo @ 2023-07-27 11:50 UTC (permalink / raw)
To: Anup Sharma
Cc: Peter Zijlstra, Ingo Molnar, Mark Rutland, Alexander Shishkin,
Jiri Olsa, Namhyung Kim, Ian Rogers, Adrian Hunter,
linux-perf-users, linux-kernel
Em Fri, Jul 21, 2023 at 11:27:46PM +0530, Anup Sharma escreveu:
> This will enable the execution of perf-gecko.py script
> using record and report commands in perf script.
> And this will be also reflected at "perf script -l" command.
>
> For Example:
> perf script record perf-gecko
> perf script report perf-gecko
But this isn't working:
[root@five ~]# perf script gecko
usage: gecko.py [-h] [--user-color USER_COLOR] [--kernel-color KERNEL_COLOR]
gecko.py: error: unrecognized arguments: -i -
[root@five ~]#
See below how this pipes the 'record' script with its 'report'
counterpart.
[root@five ~]# strace -s200 -e execve perf script gecko
execve("/root/bin/perf", ["perf", "script", "gecko"], 0x7ffd0b021c18 /* 23 vars */) = 0
execve("/bin/sh", ["/bin/sh", "/var/home/acme/libexec/perf-core/scripts/python/bin/gecko-report", "-i", "-"], 0x24a5c20 /* 26 vars */) = 0
usage: gecko.py [-h] [--user-color USER_COLOR] [--kernel-color KERNEL_COLOR]
gecko.py: error: unrecognized arguments: -i -
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=3275075, si_uid=0, si_status=2, si_utime=3 /* 0.03 s */, si_stime=0} ---
+++ exited with 2 +++
[root@five ~]#
[root@five ~]# perf record -F 99 -a -g -- sleep 5 -o - | perf script gecko
usage: gecko.py [-h] [--user-color USER_COLOR] [--kernel-color KERNEL_COLOR]
gecko.py: error: unrecognized arguments: -i -
[root@five ~]#
See it being used another script:
[root@five ~]# perf script -l
List of available trace scripts:
failed-syscalls [comm] system-wide failed syscalls
rw-by-file <comm> r/w activity for a program, by file
rw-by-pid system-wide r/w activity
rwtop [interval] system-wide r/w top
wakeup-latency system-wide min/max/avg wakeup latency
compaction-times [-h] [-u] [-p|-pv] [-t | [-m] [-fs] [-ms]] [pid|pid-range|comm-regex] display time taken by mm compaction
event_analyzing_sample analyze all perf samples
export-to-postgresql [database name] [columns] [calls] export perf data to a postgresql database
export-to-sqlite [database name] [columns] [calls] export perf data to a sqlite3 database
failed-syscalls-by-pid [comm] system-wide failed syscalls, by pid
flamegraph create flame graphs
futex-contention futext contention measurement
gecko create firefox gecko profile json format from perf.data
intel-pt-events print Intel PT Events including Power Events and PTWRITE
mem-phys-addr resolve physical address samples
net_dropmonitor display a table of dropped frames
netdev-times [tx] [rx] [dev=] [debug] display a process of packet and processing time
powerpc-hcalls
sched-migration sched migration overview
sctop [comm] [interval] syscall top
stackcollapse produce callgraphs in short form for scripting use
syscall-counts-by-pid [comm] system-wide syscall counts, by pid
syscall-counts [comm] system-wide syscall counts
task-analyzer analyze timings of tasks
[root@five ~]#
[root@five ~]# perf script futex-contention
Press control+C to stop and show the summary
^CSocket Thread[195353] lock 7f294b100018 contended 387 times, 579 avg ns [max: 32060 ns, min 390 ns]
WebrtcC~read #1[2866067] lock 7f294b100018 contended 390 times, 506 avg ns [max: 19130 ns, min 330 ns]
Socket Thread[12316] lock 7efd9479b8a0 contended 2 times, 785 avg ns [max: 910 ns, min 660 ns]
IPDL Background[12109] lock 7f7792b00018 contended 8 times, 6108 avg ns [max: 9060 ns, min 550 ns]
WebrtcWorker #3[2866076] lock 7f2922c074cc contended 5 times, 79002 avg ns [max: 133610 ns, min 22810 ns]
WebrtcWorker #4[2866078] lock 7f2922c07480 contended 19 times, 19540 avg ns [max: 57740 ns, min 4490 ns]
firefox[12080] lock 7f7792b00e18 contended 15 times, 86585 avg ns [max: 141290 ns, min 510 ns]
AudioIP~ent RPC[201969] lock 7f294b100018 contended 8 times, 1764 avg ns [max: 2440 ns, min 510 ns]
<SNIP>
TaskCon~ller #6[195531] lock 7f294b100dd8 contended 1 times, 10300 avg ns [max: 10300 ns, min 10300 ns]
Isolated Web Co[16799] lock 7ffb1d100018 contended 2 times, 7270 avg ns [max: 12450 ns, min 2090 ns]
[root@five ~]#
It will:
3275194 pts/2 S+ 0:00 strace -s200 -e execve perf script futex-contention
3275197 pts/2 S+ 0:00 /bin/sh /var/home/acme/libexec/perf-core/scripts/python/bin/futex-contention-report -i -
3275198 pts/2 S+ 0:00 /bin/sh /var/home/acme/libexec/perf-core/scripts/python/bin/futex-contention-record -a -q -o -
3275199 pts/2 Sl+ 0:00 perf record -e syscalls:sys_enter_futex -e syscalls:sys_exit_futex -a -q -o -
3275200 pts/2 S+ 0:02 perf script -i - -s /var/home/acme/libexec/perf-core/scripts/python/futex-contention.py
Create a pipe, run
/var/home/acme/libexec/perf-core/scripts/python/bin/futex-contention-record
and pipe it into /var/home/acme/libexec/perf-core/scripts/python/bin/futex-contention-report
I also renamed perf-gecko to just gecko, no need to have the 'perf-'
prefix.
Try this other script, that updates the screen periodically:
[root@five ~]# perf script rwtop
read counts by pid:
pid comm # reads bytes_req bytes_read
------ -------------------- ---------- ---------- ----------
3275423 perf 341653 16403072 16403816
3275448 Web Content 615 2503477 1419444
3275431 DOMCacheThread 318 1234020 1232492
3275466 StreamTrans #1 141 1140597 518820
12189 Cache2 I/O 193 389798 376046
12313 QuotaManager IO 81 126252 121668
3275432 StreamTrans #2 10 92305 92289
9317 fuse-overlayfs 1078 1134780416 56796
3275414 StreamT~s #6488 5 45076 45068
3275446 IndexedDB #5496 25 33892 32364
3275461 pkla-check-auth 40 67235 28513
1138 systemd-oomd 40 106560 10520
1170 polkitd 51 110776 6951
2227 pipewire 370 2960 2960
3137 gnome-terminal- 15 81104 2869
12441 MemoryPoller 3 3072 1559
2425 pipewire-pulse 185 1480 1480
2418 pipewire-pulse 185 1480 1480
12751 threaded-ml 563 5630 939
2275 gnome-shell 36 295488 888
write counts by pid:
pid comm # writes bytes_written
------ -------------------- ---------- -------------
3275424 perf 2440 68339552
12518 mozStorage #4 15 229545
12521 LS Thread 233 118752
12189 Cache2 I/O 11 21760
3275431 DOMCacheThread 4 4153
2425 pipewire-pulse 370 2960
2227 pipewire 185 1480
12751 threaded-ml 1124 1124
12080 firefox 367 371
1211 gdbus 36 288
1705 gdbus 30 240
195348 Isolated Web Co 235 235
1139 systemd-resolve 7 223
2207 gnome-shell 26 208
1545 gdbus 24 192
201970 AudioIPC0 185 185
2866066 GraphRunner 176 176
1533 geoclue 16 128
565667 gvfsd-dnssd 16 128
3275460 pcscd 15 120
[root@five ~]#
I put what I have on this branch:
git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git tmp.perf-tools-next
Later I'll try and work on have this working if you don't beat me to it
:-)
- Arnaldo
> Signed-off-by: Anup Sharma <anupnewsmail@gmail.com>
> ---
> tools/perf/scripts/python/bin/perf-gecko-record | 2 ++
> tools/perf/scripts/python/bin/perf-gecko-report | 3 +++
> 2 files changed, 5 insertions(+)
> create mode 100644 tools/perf/scripts/python/bin/perf-gecko-record
> create mode 100644 tools/perf/scripts/python/bin/perf-gecko-report
>
> diff --git a/tools/perf/scripts/python/bin/perf-gecko-record b/tools/perf/scripts/python/bin/perf-gecko-record
> new file mode 100644
> index 000000000000..7df5a19c0163
> --- /dev/null
> +++ b/tools/perf/scripts/python/bin/perf-gecko-record
> @@ -0,0 +1,2 @@
> +#!/bin/bash
> +perf record -g "$@"
> diff --git a/tools/perf/scripts/python/bin/perf-gecko-report b/tools/perf/scripts/python/bin/perf-gecko-report
> new file mode 100644
> index 000000000000..6781313dc862
> --- /dev/null
> +++ b/tools/perf/scripts/python/bin/perf-gecko-report
> @@ -0,0 +1,3 @@
> +#!/bin/bash
> +# description: create firefox gecko profile json format from perf.data
> +perf script -s "$PERF_EXEC_PATH"/scripts/python/perf-gecko.py -- "$@"
> --
> 2.34.1
>
--
- Arnaldo
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2023-07-27 11:50 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-21 17:51 [PATCH v5 0/8] Add support for Firefox's gecko profile format Anup Sharma
2023-07-21 17:52 ` [PATCH v5 1/8] perf scripts python: Add initial script file with usage information Anup Sharma
2023-07-21 17:52 ` [PATCH v5 2/8] perf scripts python: Extact necessary information from process event Anup Sharma
2023-07-21 17:53 ` [PATCH v5 3/8] perf scripts python: Add classes and conversion functions Anup Sharma
2023-07-21 17:54 ` [PATCH v5 4/8] perf scripts python: Add trace end processing and PRODUCT and CATEGORIES information Anup Sharma
2023-07-21 17:55 ` [PATCH v5 5/8] perf scripts python: Implement add sample function and thread processing Anup Sharma
2023-07-21 17:56 ` [PATCH v5 6/8] " Anup Sharma
2023-07-21 17:57 ` [PATCH v5 7/8] perf scripts python: Add command execution for perf gecko script Anup Sharma
2023-07-27 11:50 ` Arnaldo Carvalho de Melo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).