~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/scripts/python/gecko.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/perf/scripts/python/gecko.py (Version linux-6.12-rc7) and /tools/perf/scripts/python/gecko.py (Version linux-5.2.21)


  1 # gecko.py - Convert perf record output to Fir    
  2 # SPDX-License-Identifier: GPL-2.0                
  3 #                                                 
  4 # The script converts perf.data to Gecko Profi    
  5 # which can be read by https://profiler.firefo    
  6 #                                                 
  7 # Usage:                                          
  8 #                                                 
  9 #     perf record -a -g -F 99 sleep 60            
 10 #     perf script report gecko                    
 11 #                                                 
 12 # Combined:                                       
 13 #                                                 
 14 #     perf script gecko -F 99 -a sleep 60         
 15                                                   
 16 import os                                         
 17 import sys                                        
 18 import time                                       
 19 import json                                       
 20 import string                                     
 21 import random                                     
 22 import argparse                                   
 23 import threading                                  
 24 import webbrowser                                 
 25 import urllib.parse                               
 26 from os import system                             
 27 from functools import reduce                      
 28 from dataclasses import dataclass, field          
 29 from http.server import HTTPServer, SimpleHTTP    
 30 from typing import List, Dict, Optional, Named    
 31                                                   
 32 # Add the Perf-Trace-Util library to the Pytho    
 33 sys.path.append(os.environ['PERF_EXEC_PATH'] +    
 34         '/scripts/python/Perf-Trace-Util/lib/P    
 35                                                   
 36 from perf_trace_context import *                  
 37 from Core import *                                
 38                                                   
 39 StringID = int                                    
 40 StackID = int                                     
 41 FrameID = int                                     
 42 CategoryID = int                                  
 43 Milliseconds = float                              
 44                                                   
 45 # start_time is intialiazed only once for the     
 46 start_time = None                                 
 47                                                   
 48 # https://github.com/firefox-devtools/profiler    
 49 # Follow Brendan Gregg's Flamegraph convention    
 50 CATEGORIES = None                                 
 51                                                   
 52 # The product name is used by the profiler UI     
 53 PRODUCT = os.popen('uname -op').read().strip()    
 54                                                   
 55 # store the output file                           
 56 output_file = None                                
 57                                                   
 58 # Here key = tid, value = Thread                  
 59 tid_to_thread = dict()                            
 60                                                   
 61 # The HTTP server is used to serve the profile    
 62 http_server_thread = None                         
 63                                                   
 64 # The category index is used by the profiler U    
 65 USER_CATEGORY_INDEX = 0                           
 66 KERNEL_CATEGORY_INDEX = 1                         
 67                                                   
 68 # https://github.com/firefox-devtools/profiler    
 69 class Frame(NamedTuple):                          
 70         string_id: StringID                       
 71         relevantForJS: bool                       
 72         innerWindowID: int                        
 73         implementation: None                      
 74         optimizations: None                       
 75         line: None                                
 76         column: None                              
 77         category: CategoryID                      
 78         subcategory: int                          
 79                                                   
 80 # https://github.com/firefox-devtools/profiler    
 81 class Stack(NamedTuple):                          
 82         prefix_id: Optional[StackID]              
 83         frame_id: FrameID                         
 84                                                   
 85 # https://github.com/firefox-devtools/profiler    
 86 class Sample(NamedTuple):                         
 87         stack_id: Optional[StackID]               
 88         time_ms: Milliseconds                     
 89         responsiveness: int                       
 90                                                   
 91 @dataclass                                        
 92 class Thread:                                     
 93         """A builder for a profile of the thre    
 94                                                   
 95         Attributes:                               
 96                 comm: Thread command-line (nam    
 97                 pid: process ID of containing     
 98                 tid: thread ID.                   
 99                 samples: Timeline of profile s    
100                 frameTable: interned stack fra    
101                 stringTable: interned string I    
102                 stringMap: interned string ->     
103                 stackTable: interned stack ID     
104                 stackMap: (stack prefix ID, le    
105                 frameMap: Stack Frame string -    
106                 comm: str                         
107                 pid: int                          
108                 tid: int                          
109                 samples: List[Sample] = field(    
110                 frameTable: List[Frame] = fiel    
111                 stringTable: List[str] = field    
112                 stringMap: Dict[str, int] = fi    
113                 stackTable: List[Stack] = fiel    
114                 stackMap: Dict[Tuple[Optional[    
115                 frameMap: Dict[str, int] = fie    
116         """                                       
117         comm: str                                 
118         pid: int                                  
119         tid: int                                  
120         samples: List[Sample] = field(default_    
121         frameTable: List[Frame] = field(defaul    
122         stringTable: List[str] = field(default    
123         stringMap: Dict[str, int] = field(defa    
124         stackTable: List[Stack] = field(defaul    
125         stackMap: Dict[Tuple[Optional[int], in    
126         frameMap: Dict[str, int] = field(defau    
127                                                   
128         def _intern_stack(self, frame_id: int,    
129                 """Gets a matching stack, or s    
130                 key = f"{frame_id}" if prefix_    
131                 # key = (prefix_id, frame_id)     
132                 stack_id = self.stackMap.get(k    
133                 if stack_id is None:              
134                         # return stack_id         
135                         stack_id = len(self.st    
136                         self.stackTable.append    
137                         self.stackMap[key] = s    
138                 return stack_id                   
139                                                   
140         def _intern_string(self, string: str)     
141                 """Gets a matching string, or     
142                 string_id = self.stringMap.get    
143                 if string_id is not None:         
144                         return string_id          
145                 string_id = len(self.stringTab    
146                 self.stringTable.append(string    
147                 self.stringMap[string] = strin    
148                 return string_id                  
149                                                   
150         def _intern_frame(self, frame_str: str    
151                 """Gets a matching stack frame    
152                 frame_id = self.frameMap.get(f    
153                 if frame_id is not None:          
154                         return frame_id           
155                 frame_id = len(self.frameTable    
156                 self.frameMap[frame_str] = fra    
157                 string_id = self._intern_strin    
158                                                   
159                 symbol_name_to_category = KERN    
160                 or frame_str.find('/vmlinux')     
161                 or frame_str.endswith('.ko)')     
162                 else USER_CATEGORY_INDEX          
163                                                   
164                 self.frameTable.append(Frame(     
165                         string_id=string_id,      
166                         relevantForJS=False,      
167                         innerWindowID=0,          
168                         implementation=None,      
169                         optimizations=None,       
170                         line=None,                
171                         column=None,              
172                         category=symbol_name_t    
173                         subcategory=None,         
174                 ))                                
175                 return frame_id                   
176                                                   
177         def _add_sample(self, comm: str, stack    
178                 """Add a timestamped stack tra    
179                 Args:                             
180                         comm: command-line (na    
181                         stack: sampled stack f    
182                         time_ms: timestamp of     
183                 """                               
184                 # Ihreads may not set their na    
185                 # Instead, they might do it la    
186                 if self.comm != comm:             
187                         self.comm = comm          
188                                                   
189                 prefix_stack_id = reduce(lambd    
190                                                   
191                 if prefix_stack_id is not None    
192                         self.samples.append(Sa    
193                                                   
194                                                   
195                                                   
196         def _to_json_dict(self) -> Dict:          
197                 """Converts current Thread to     
198                 # Gecko profile format is row-    
199                 # And a schema for interpretin    
200                 # Schema:                         
201                 # https://github.com/firefox-d    
202                 # https://github.com/firefox-d    
203                 return {                          
204                         "tid": self.tid,          
205                         "pid": self.pid,          
206                         "name": self.comm,        
207                         # https://github.com/f    
208                         "markers": {              
209                                 "schema": {       
210                                         "name"    
211                                         "start    
212                                         "endTi    
213                                         "phase    
214                                         "categ    
215                                         "data"    
216                                 },                
217                                 "data": [],       
218                         },                        
219                                                   
220                         # https://github.com/f    
221                         "samples": {              
222                                 "schema": {       
223                                         "stack    
224                                         "time"    
225                                         "respo    
226                                 },                
227                                 "data": self.s    
228                         },                        
229                                                   
230                         # https://github.com/f    
231                         "frameTable": {           
232                                 "schema": {       
233                                         "locat    
234                                         "relev    
235                                         "inner    
236                                         "imple    
237                                         "optim    
238                                         "line"    
239                                         "colum    
240                                         "categ    
241                                         "subca    
242                                 },                
243                                 "data": self.f    
244                         },                        
245                                                   
246                         # https://github.com/f    
247                         "stackTable": {           
248                                 "schema": {       
249                                         "prefi    
250                                         "frame    
251                                 },                
252                                 "data": self.s    
253                         },                        
254                         "stringTable": self.st    
255                         "registerTime": 0,        
256                         "unregisterTime": None    
257                         "processType": "defaul    
258                 }                                 
259                                                   
260 # Uses perf script python interface to parse e    
261 # event and store the data in the thread build    
262 def process_event(param_dict: Dict) -> None:      
263         global start_time                         
264         global tid_to_thread                      
265         time_stamp = (param_dict['sample']['ti    
266         pid = param_dict['sample']['pid']         
267         tid = param_dict['sample']['tid']         
268         comm = param_dict['comm']                 
269                                                   
270         # Start time is the time of the first     
271         if not start_time:                        
272                 start_time = time_stamp           
273                                                   
274         # Parse and append the callchain of th    
275         stack = []                                
276         if param_dict['callchain']:               
277                 for call in param_dict['callch    
278                         if 'sym' not in call:     
279                                 continue          
280                         stack.append(f'{call["    
281                 if len(stack) != 0:               
282                         # Reverse the stack, a    
283                         stack = stack[::-1]       
284                                                   
285         # During perf record if -g is not used    
286         # In that case, the symbol and dso are    
287         else:                                     
288                 func = param_dict['symbol'] if    
289                 dso = param_dict['dso'] if 'ds    
290                 stack.append(f'{func} (in {dso    
291                                                   
292         # Add sample to the specific thread.      
293         thread = tid_to_thread.get(tid)           
294         if thread is None:                        
295                 thread = Thread(comm=comm, pid    
296                 tid_to_thread[tid] = thread       
297         thread._add_sample(comm=comm, stack=st    
298                                                   
299 def trace_begin() -> None:                        
300         global output_file                        
301         if (output_file is None):                 
302                 print("Staring Firefox Profile    
303                 global http_server_thread         
304                 http_server_thread = threading    
305                 http_server_thread.daemon = Tr    
306                 http_server_thread.start()        
307                                                   
308 # Trace_end runs at the end and will be used t    
309 # the data into the final json object and prin    
310 def trace_end() -> None:                          
311         global output_file                        
312         threads = [thread._to_json_dict() for     
313                                                   
314         # Schema: https://github.com/firefox-d    
315         gecko_profile_with_meta = {               
316                 "meta": {                         
317                         "interval": 1,            
318                         "processType": 0,         
319                         "product": PRODUCT,       
320                         "stackwalk": 1,           
321                         "debug": 0,               
322                         "gcpoison": 0,            
323                         "asyncstack": 1,          
324                         "startTime": start_tim    
325                         "shutdownTime": None,     
326                         "version": 24,            
327                         "presymbolicated": Tru    
328                         "categories": CATEGORI    
329                         "markerSchema": [],       
330                         },                        
331                 "libs": [],                       
332                 "threads": threads,               
333                 "processes": [],                  
334                 "pausedRanges": [],               
335         }                                         
336         # launch the profiler on local host if    
337         if (output_file is None):                 
338                 output_file = 'gecko_profile.j    
339                 with open(output_file, 'w') as    
340                         json.dump(gecko_profil    
341                 launchFirefox(output_file)        
342                 time.sleep(1)                     
343                 print(f'[ perf gecko: Captured    
344         else:                                     
345                 print(f'[ perf gecko: Captured    
346                 with open(output_file, 'w') as    
347                         json.dump(gecko_profil    
348                                                   
349 # Used to enable Cross-Origin Resource Sharing    
350 class CORSRequestHandler(SimpleHTTPRequestHand    
351         def end_headers (self):                   
352                 self.send_header('Access-Contr    
353                 SimpleHTTPRequestHandler.end_h    
354                                                   
355 # start a local server to serve the gecko_prof    
356 def launchFirefox(file):                          
357         safe_string = urllib.parse.quote_plus(    
358         url = 'https://profiler.firefox.com/fr    
359         webbrowser.open(f'{url}')                 
360                                                   
361 def main() -> None:                               
362         global output_file                        
363         global CATEGORIES                         
364         parser = argparse.ArgumentParser(descr    
365                                                   
366         # Add the command-line options            
367         # Colors must be defined according to     
368         # https://github.com/firefox-devtools/    
369         parser.add_argument('--user-color', de    
370         parser.add_argument('--kernel-color',     
371         # If --save-only is specified, the out    
372         parser.add_argument('--save-only', hel    
373                                                   
374         # Parse the command-line arguments        
375         args = parser.parse_args()                
376         # Access the values provided by the us    
377         user_color = args.user_color              
378         kernel_color = args.kernel_color          
379         output_file = args.save_only              
380                                                   
381         CATEGORIES = [                            
382                 {                                 
383                         "name": 'User',           
384                         "color": user_color,      
385                         "subcategories": ['Oth    
386                 },                                
387                 {                                 
388                         "name": 'Kernel',         
389                         "color": kernel_color,    
390                         "subcategories": ['Oth    
391                 },                                
392         ]                                         
393                                                   
394 if __name__ == '__main__':                        
395         main()                                    
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php