hcttracei.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #!/usr/bin/env python2.7
  2. # Copyright (C) Microsoft Corporation. All rights reserved.
  3. # This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details.
  4. """Analyses the ETW dump file fors dxcompiler output as generated by hcttrace."""
  5. import argparse
  6. import datetime
  7. import xml.etree.ElementTree as ET
  8. # Task values.
  9. DXCompilerInitialization = 1;
  10. DXCompilerShutdown = 2;
  11. DXCompilerCreateInstance = 3;
  12. DXCompilerIntelliSenseParse = 4;
  13. DXCompilerCompile = 5;
  14. DXCompilerPreprocess = 6;
  15. DXCompilerDisassemble = 7;
  16. # Opcode values
  17. OpcodeStart = 1;
  18. OpcodeStop = 2;
  19. # Namespace dictionary.
  20. ns = {'e': 'http://schemas.microsoft.com/win/2004/08/events/event'}
  21. def write_basic_info(node):
  22. '''Writes computer information'''
  23. print("Basic information:")
  24. print("CPU Speed: %s" % node.find("e:Data[@Name='CPUSpeed']", ns). text)
  25. print("Processor count: %s" % node.find("e:Data[@Name='NumberOfProcessors']", ns). text)
  26. print("Events lost: %s" % node.find("e:Data[@Name='EventsLost']", ns). text)
  27. print("Pointer size: %s" % node.find("e:Data[@Name='PointerSize']", ns). text)
  28. def write_compile_times(root):
  29. '''Prints out compilation times.'''
  30. compilations = {}
  31. for e in root:
  32. system_node = e.find("e:System", ns)
  33. if system_node is None:
  34. continue
  35. channel = system_node.find("e:Channel", ns)
  36. if channel is None or channel.text <> "Microsoft-Windows-DXCompiler-API/Analytic":
  37. continue
  38. task = int(system_node.find("e:Task", ns).text)
  39. opcode = int(system_node.find("e:Opcode", ns).text)
  40. pid = int(system_node.find("e:Execution", ns).attrib['ProcessID'])
  41. tid = int(system_node.find("e:Execution", ns).attrib['ThreadID'])
  42. time_created = system_node.find("e:TimeCreated", ns).attrib['SystemTime']
  43. # Something like:
  44. # 2016-02-02T00:10:51.619434100Z
  45. # Unfortunately datetime doesn't have enough precision, so we make do with this:
  46. # 2016-02-02T00:10:39.630081
  47. if task == DXCompilerCompile:
  48. time_created = time_created[:26]
  49. cid = '{0},{1}'.format(pid, tid)
  50. parsed_time_created = datetime.datetime.strptime(time_created, "%Y-%m-%dT%H:%M:%S.%f")
  51. if opcode == OpcodeStart:
  52. #print "Start at %s" % time_created
  53. compilations[cid] = parsed_time_created
  54. else:
  55. old_parsed_time_created = compilations[cid]
  56. print "Compilation took %s" % str(parsed_time_created - old_parsed_time_created)
  57. def main():
  58. parser = argparse.ArgumentParser(description=__doc__)
  59. parser.add_argument('-v', '--verbose', action='store_true',
  60. help='Show verbose output')
  61. parser.add_argument('dumpfiles', nargs='+')
  62. args = parser.parse_args()
  63. for dumpfile in args.dumpfiles:
  64. if args.verbose:
  65. print >>sys.stderr, 'Scanning for dxcompiler events in dumpfile: %s' % (dumpfile,)
  66. tree = ET.parse(dumpfile)
  67. root = tree.getroot()
  68. write_basic_info(root.find('e:Event/e:EventData', ns))
  69. write_compile_times(root)
  70. # Other interesting things:
  71. # errors, working set, additional stats
  72. if __name__ == '__main__':
  73. main()