Skip to content

Instantly share code, notes, and snippets.

@mbrucher
Last active August 29, 2015 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mbrucher/6cad31e38beca770523b to your computer and use it in GitHub Desktop.
Save mbrucher/6cad31e38beca770523b to your computer and use it in GitHub Desktop.
Script to convert from XML HPCToolkit format to callgrind
#!/usr/bin/env python
from xml.sax import ContentHandler, make_parser
from collections import defaultdict
class HPCToolKitHandler(ContentHandler):
def __init__(self, f):
self.f = f
self.metrics = {}
self.files = {}
self.functions = {}
self.cumulative_metrics = [defaultdict(int)]
self.strings = []
self.stack = []
def startElement(self, name, attrs):
if name == "MetricTable":
pass
elif name == "Metric":
self.process_metric(attrs)
elif name == "File":
self.process_file(attrs)
elif name == "Procedure":
self.process_procedure(attrs)
elif name == "PF":
self.process_PF(attrs)
elif name == "PR":
self.process_PF(attrs)
elif name == "S":
self.process_site(attrs)
elif name == "C":
self.process_call(attrs)
elif name == "M":
self.process_measure(attrs)
def endElement(self, name):
if name == "MetricTable":
self.dump_metrics()
elif name == "Metric":
pass
elif name == "File":
pass
elif name == "Procedure":
pass
elif name == "PF":
self.process_PF_end()
elif name == "PR":
self.process_PF_end()
elif name == "S":
self.process_site_end()
elif name == "C":
self.process_call_end()
elif name == "M":
pass
def dump_metrics(self):
self.metrics_keys = self.metrics.keys()
self.metrics_keys.sort()
self.f.write("events: " + " ".join(self.metrics[key] for key in self.metrics_keys) + "\n")
def process_metric(self, attrs):
i = -1
name = None
for (k,v) in attrs.items():
if k == "i":
i = int(v)
if k == "n":
name = v.replace(" ", "_")
self.metrics[i] = name
def process_measure(self, attrs):
i = -1
value = 0
for (k,v) in attrs.items():
if k == "n":
i = int(v)
if k == "v":
value = int(float(v))
self.cumulative_metrics[-1][i] = value
def process_file(self, attrs):
i = -1
name = None
for (k,v) in attrs.items():
if k == "i":
i = int(v)
elif k == "n":
name = v.replace(" ", "_")
self.files[i] = name
def process_procedure(self, attrs):
i = -1
name = None
for (k,v) in attrs.items():
if k == "i":
i = int(v)
elif k == "n":
name = v.replace(" ", "_")
self.functions[i] = name
def process_PF(self, attrs):
self.cumulative_metrics.append(defaultdict(int))
self.stack.append((len(self.strings), dict(attrs.items())))
self.strings.append(u"""fl=%s
fn=%s
""" % (self.files[int(attrs["f"])], self.functions[int(attrs["n"])]))
def process_PF_end(self):
# Finish current method by a new line
self.strings[self.stack[-1][0]] += "\n"
called = self.stack.pop()
metrics = self.cumulative_metrics.pop()
for key in metrics:
self.cumulative_metrics[-1][key] += metrics[key]
if len(self.stack):
self.strings[self.stack[-1][0]] += """cfl=%s
cfn=%s
calls=1 %s
%s %s
""" % (self.files[int(called[1]["f"])], self.functions[int(called[1]["n"])], called[1]["l"], self.stack[-1][1]["l"], " ".join((str(metrics[key]) for key in self.metrics_keys)))
def process_site(self, attrs):
self.cumulative_metrics.append(defaultdict(int))
self.stack.append((self.stack[-1][0], dict(attrs.items())))
def process_site_end(self):
self.strings[self.stack[-1][0]] += (self.stack[-1][1]["l"] + " " + " ".join((str(self.cumulative_metrics[-1][key]) for key in self.metrics_keys)) + "\n")
self.stack.pop()
metrics = self.cumulative_metrics.pop()
print metrics
for key in metrics:
self.cumulative_metrics[-1][key] += metrics[key]
def process_call(self, attrs):
self.stack.append((self.stack[-1][0], dict(attrs.items())))
def process_call_end(self):
self.stack.pop()
def dump(self):
self.f.writelines(self.strings)
if __name__ == "__main__":
import sys
parser = make_parser()
handler = HPCToolKitHandler(open(sys.argv[2],"w"))
parser.setContentHandler(handler)
parser.parse(open(sys.argv[1],"r"))
handler.dump()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment