Mesa (main): gallium/tools: add option for ignoring junk calls in trace dumper

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jun 28 12:13:49 UTC 2022


Module: Mesa
Branch: main
Commit: 6f70a1cd140fbf7752678d1bfc5fa972da4120bf
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=6f70a1cd140fbf7752678d1bfc5fa972da4120bf

Author: Matti Hamalainen <ccr at tnsp.org>
Date:   Fri Jan 21 23:35:33 2022 +0200

gallium/tools: add option for ignoring junk calls in trace dumper

Previously tracediff.sh used postprocessing sed-script to remove unwanted
calls from the dump output. Instead of that, add option to parse.py to
ignore a list of calls at parsing phase. Currently this list is hardcoded
in parse.py.

Also clean up the trace model code and pointer tracking a bit to avoid
static state in Pointer class.

Signed-off-by: Matti Hamalainen <ccr at tnsp.org>
Acked-by: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Reviewed-by: Dylan Baker <dylan at pnwbakers.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17135>

---

 src/gallium/tools/trace/dump_state.py |  6 ++--
 src/gallium/tools/trace/model.py      | 51 ++++++++++++++------------
 src/gallium/tools/trace/parse.py      | 67 +++++++++++++++++++++++++----------
 src/gallium/tools/trace/tracediff.sh  |  4 +--
 4 files changed, 81 insertions(+), 47 deletions(-)

diff --git a/src/gallium/tools/trace/dump_state.py b/src/gallium/tools/trace/dump_state.py
index 0d5548d7387..9c439ea02f4 100755
--- a/src/gallium/tools/trace/dump_state.py
+++ b/src/gallium/tools/trace/dump_state.py
@@ -780,8 +780,8 @@ class Interpreter(parser.SimpleTraceDumper):
             ('pipe_context', 'transfer_unmap'),
     ))
 
-    def __init__(self, stream, options, formatter):
-        parser.SimpleTraceDumper.__init__(self, stream, options, formatter)
+    def __init__(self, stream, options, formatter, state):
+        parser.SimpleTraceDumper.__init__(self, stream, options, formatter, state)
         self.objects = {}
         self.result = None
         self.globl = Global(self)
@@ -878,7 +878,7 @@ class Main(parser.Main):
 
     def process_arg(self, stream, options):
         formatter = format.Formatter(sys.stderr)
-        parser = Interpreter(stream, options, formatter)
+        parser = Interpreter(stream, options, formatter, model.TraceStateData())
         parser.parse()
 
 
diff --git a/src/gallium/tools/trace/model.py b/src/gallium/tools/trace/model.py
index 943f97b8c1a..0c7130aaa6c 100755
--- a/src/gallium/tools/trace/model.py
+++ b/src/gallium/tools/trace/model.py
@@ -56,6 +56,14 @@ class ModelOptions:
                     self.__dict__[var] = args.__dict__[var]
 
 
+class TraceStateData:
+
+    def __init__(self):
+        self.ptr_list = {}
+        self.ptr_type_list = {}
+        self.ptr_types_list = {}
+
+
 class Node:
     
     def visit(self, visitor):
@@ -81,14 +89,10 @@ class Literal(Node):
 class Blob(Node):
     
     def __init__(self, value):
-        self._rawValue = None
-        self._hexValue = value
+        self.value = binascii.a2b_hex(value)
 
     def getValue(self):
-        if self._rawValue is None:
-            self._rawValue = binascii.a2b_hex(self._hexValue)
-            self._hexValue = None
-        return self._rawValue
+        return self.value
 
     def visit(self, visitor):
         visitor.visit_blob(self)
@@ -123,19 +127,18 @@ class Struct(Node):
 
         
 class Pointer(Node):
-    
-    ptr_list = {}
-    ptr_type_list = {}
-    ptr_types_list = {}
+
     ptr_ignore_list = ["ret", "elem"]
 
-    def __init__(self, address, pname):
+    def __init__(self, state, address, pname):
         self.address = address
+        self.pname = pname
+        self.state = state
 
         # Check if address exists in list and if it is a return value address
-        t1 = address in self.ptr_list
+        t1 = address in state.ptr_list
         if t1:
-            rname = self.ptr_type_list[address]
+            rname = state.ptr_type_list[address]
             t2 = rname in self.ptr_ignore_list and pname not in self.ptr_ignore_list
         else:
             rname = pname
@@ -149,15 +152,18 @@ class Pointer(Node):
 
             # Add / update
             self.adjust_ptr_type_count(pname, 1)
-            tmp = "{}_{}".format(pname, self.ptr_types_list[pname])
-            self.ptr_list[address] = tmp
-            self.ptr_type_list[address] = pname
+            tmp = "{}_{}".format(pname, state.ptr_types_list[pname])
+            state.ptr_list[address] = tmp
+            state.ptr_type_list[address] = pname
 
     def adjust_ptr_type_count(self, pname, delta):
-        if pname not in self.ptr_types_list:
-            self.ptr_types_list[pname] = 0
+        if pname not in self.state.ptr_types_list:
+            self.state.ptr_types_list[pname] = 0
+
+        self.state.ptr_types_list[pname] += delta
 
-        self.ptr_types_list[pname] += delta
+    def named_address(self):
+        return self.state.ptr_list[self.address]
 
     def visit(self, visitor):
         visitor.visit_pointer(self)
@@ -258,13 +264,13 @@ class PrettyPrinter:
     
     def visit_pointer(self, node):
         if self.options.named_ptrs:
-            self.formatter.address(node.ptr_list[node.address])
+            self.formatter.address(node.named_address())
         else:
             self.formatter.address(node.address)
 
     def visit_call(self, node):
         if not self.options.suppress_variants:
-            self.formatter.text('%s ' % node.no)
+            self.formatter.text(f'{node.no} ')
 
         if node.klass is not None:
             self.formatter.function(node.klass + '::' + node.method)
@@ -289,8 +295,9 @@ class PrettyPrinter:
             self.formatter.text(' // time ')
             node.time.visit(self)
 
+        self.formatter.newline()
+
     def visit_trace(self, node):
         for call in node.calls:
             call.visit(self)
-            self.formatter.newline()
 
diff --git a/src/gallium/tools/trace/parse.py b/src/gallium/tools/trace/parse.py
index ecd5424e6c1..f86b533cee5 100755
--- a/src/gallium/tools/trace/parse.py
+++ b/src/gallium/tools/trace/parse.py
@@ -36,6 +36,22 @@ import format
 from model import *
 
 
+trace_ignore_calls = set((
+    ("pipe_screen", "is_format_supported"),
+    ("pipe_screen", "get_name"),
+    ("pipe_screen", "get_vendor"),
+    ("pipe_screen", "get_param"),
+    ("pipe_screen", "get_paramf"),
+    ("pipe_screen", "get_shader_param"),
+    ("pipe_screen", "get_compute_param"),
+    ("pipe_screen", "get_disk_shader_cache"),
+))
+
+
+def trace_call_ignore(call):
+    return (call.klass, call.method) in trace_ignore_calls
+
+
 ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4)
 
 
@@ -192,15 +208,18 @@ class XmlParser:
 
 class TraceParser(XmlParser):
 
-    def __init__(self, fp):
+    def __init__(self, fp, options, state):
         XmlParser.__init__(self, fp)
         self.last_call_no = 0
-    
+        self.state = state
+        self.options = options
+
     def parse(self):
         self.element_start('trace')
         while self.token.type not in (ELEMENT_END, EOF):
             call = self.parse_call()
-            self.handle_call(call)
+            if not self.options.ignore_junk or not trace_call_ignore(call):
+                self.handle_call(call)
         if self.token.type != EOF:
             self.element_end('trace')
 
@@ -347,7 +366,7 @@ class TraceParser(XmlParser):
         address = self.character_data()
         self.element_end('ptr')
 
-        return Pointer(address, pname)
+        return Pointer(self.state, address, pname)
 
     def handle_call(self, call):
         pass
@@ -355,21 +374,20 @@ class TraceParser(XmlParser):
     
 class SimpleTraceDumper(TraceParser):
     
-    def __init__(self, fp, options, formatter):
-        TraceParser.__init__(self, fp)
+    def __init__(self, fp, options, formatter, state):
+        TraceParser.__init__(self, fp, options, state)
         self.options = options
         self.formatter = formatter
         self.pretty_printer = PrettyPrinter(self.formatter, options)
 
     def handle_call(self, call):
         call.visit(self.pretty_printer)
-        self.formatter.newline()
 
 
 class TraceDumper(SimpleTraceDumper):
 
-    def __init__(self, fp, options, formatter):
-        SimpleTraceDumper.__init__(self, fp, options, formatter)
+    def __init__(self, fp, options, formatter, state):
+        SimpleTraceDumper.__init__(self, fp, options, formatter, state)
         self.call_stack = []
 
     def handle_call(self, call):
@@ -377,12 +395,6 @@ class TraceDumper(SimpleTraceDumper):
             self.call_stack.append(call)
         else:
             call.visit(self.pretty_printer)
-            self.formatter.newline()
-
-    def dump_calls(self):
-        for call in self.call_stack:
-            call.visit(self.pretty_printer)
-            self.formatter.newline()
 
 
 class ParseOptions(ModelOptions):
@@ -390,6 +402,7 @@ class ParseOptions(ModelOptions):
     def __init__(self, args=None):
         # Initialize options local to this module
         self.plain = False
+        self.ignore_junk = False
 
         ModelOptions.__init__(self, args)
 
@@ -425,23 +438,38 @@ class Main:
         return ParseOptions(args)
 
     def get_optparser(self):
+        estr = "\nList of junk calls:\n"
+        for klass, call in sorted(trace_ignore_calls):
+            estr += f"  {klass}::{call}\n"
+
         optparser = argparse.ArgumentParser(
-            description="Parse and dump Gallium trace(s)")
+            description="Parse and dump Gallium trace(s)",
+            formatter_class=argparse.RawDescriptionHelpFormatter,
+            epilog=estr)
+
         optparser.add_argument("filename", action="extend", nargs="+",
             type=str, metavar="filename", help="Gallium trace filename (plain or .gz, .bz2)")
+
         optparser.add_argument("-p", "--plain",
             action="store_const", const=True, default=False,
             dest="plain", help="disable ANSI color etc. formatting")
+
         optparser.add_argument("-S", "--suppress",
             action="store_const", const=True, default=False,
             dest="suppress_variants", help="suppress some variants in output for better diffability")
+
         optparser.add_argument("-N", "--named",
             action="store_const", const=True, default=False,
             dest="named_ptrs", help="generate symbolic names for raw pointer values")
+
         optparser.add_argument("-M", "--method-only",
             action="store_const", const=True, default=False,
             dest="method_only", help="output only call names without arguments")
 
+        optparser.add_argument("-I", "--ignore-junk",
+            action="store_const", const=True, default=False,
+            dest="ignore_junk", help="filter out/ignore junk calls (see below)")
+
         return optparser
 
     def process_arg(self, stream, options):
@@ -450,11 +478,12 @@ class Main:
         else:
             formatter = format.DefaultFormatter(sys.stdout)
 
-        parser = TraceDumper(stream, options, formatter)
-        parser.parse()
+        dump = TraceDumper(stream, options, formatter, TraceStateData())
+        dump.parse()
 
         if options.named_ptrs:
-            parser.dump_calls()
+            for call in dump.call_stack:
+                call.visit(dump.pretty_printer)
 
 
 if __name__ == '__main__':
diff --git a/src/gallium/tools/trace/tracediff.sh b/src/gallium/tools/trace/tracediff.sh
index d4aaff7d0d3..4b25ebc6f6b 100755
--- a/src/gallium/tools/trace/tracediff.sh
+++ b/src/gallium/tools/trace/tracediff.sh
@@ -81,11 +81,9 @@ strip_dump()
   INFILE="$1"
   OUTFILE="$2"
 
-  python3 "$TRACEDUMP" --plain --suppress \
+  python3 "$TRACEDUMP" --plain --suppress --ignore-junk \
     "${DUMP_ARGS[@]}" "$INFILE" \
   | sed \
-    -e '/pipe_screen::is_format_supported/d' \
-    -e '/pipe_screen::get_\(shader_\)\?paramf\?/d' \
     -e 's/\r$//g' \
     -e 's/, /,\n\t/g' \
     -e 's/) = /)\n\t= /' \



More information about the mesa-commit mailing list