perf_tests_timing.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #!/usr/bin/env python
  2. """ Prints total execution time and number of total/failed tests.
  3. Performance data is stored in the GTest log file created by performance tests. Default name is
  4. `test_details.xml`. It can be changed with the `--gtest_output=xml:<location>/<filename>.xml` test
  5. option. See https://github.com/opencv/opencv/wiki/HowToUsePerfTests for more details.
  6. This script uses XML test log to produce basic runtime statistics in a text or HTML table.
  7. ### Example:
  8. ./perf_tests_timing.py opencv_perf_core.xml
  9. Overall time: 222.71 min
  10. Module Testsuit Time (min) Num of tests Failed
  11. opencv Gemm::OCL_GemmFixture 113.669 24
  12. opencv dft::Size_MatType_FlagsType_NzeroRows 21.127 180
  13. opencv Dft::OCL_DftFixture 11.153 144
  14. opencv convertTo::Size_DepthSrc_DepthDst_Channels_alpha 7.992 392
  15. opencv Normalize::OCL_NormalizeFixture 5.412 96
  16. ... ... ... ...
  17. """
  18. from __future__ import print_function
  19. import testlog_parser, sys, os, xml, glob, re
  20. from table_formatter import *
  21. from optparse import OptionParser
  22. from operator import itemgetter, attrgetter
  23. from summary import getSetName, alphanum_keyselector
  24. import re
  25. if __name__ == "__main__":
  26. usage = "%prog <log_name>.xml [...]"
  27. parser = OptionParser(usage = usage)
  28. parser.add_option("-o", "--output", dest = "format",
  29. help = "output results in text format (can be 'txt', 'html' or 'auto' - default)",
  30. metavar = 'FMT', default = 'auto')
  31. parser.add_option("--failed-only", action = "store_true", dest = "failedOnly",
  32. help = "print only failed tests", default = False)
  33. (options, args) = parser.parse_args()
  34. options.generateHtml = detectHtmlOutputType(options.format)
  35. files = []
  36. testsuits = [] # testsuit module, name, time, num, flag for failed tests
  37. overall_time = 0
  38. seen = set()
  39. for arg in args:
  40. if ("*" in arg) or ("?" in arg):
  41. flist = [os.path.abspath(f) for f in glob.glob(arg)]
  42. flist = sorted(flist, key= lambda text: str(text).replace("M", "_"))
  43. files.extend([ x for x in flist if x not in seen and not seen.add(x)])
  44. else:
  45. fname = os.path.abspath(arg)
  46. if fname not in seen and not seen.add(fname):
  47. files.append(fname)
  48. file = os.path.abspath(fname)
  49. if not os.path.isfile(file):
  50. sys.stderr.write("IOError reading \"" + file + "\" - " + str(err) + os.linesep)
  51. parser.print_help()
  52. exit(0)
  53. fname = os.path.basename(fname)
  54. find_module_name = re.search(r'([^_]*)', fname)
  55. module_name = find_module_name.group(0)
  56. test_sets = []
  57. try:
  58. tests = testlog_parser.parseLogFile(file)
  59. if tests:
  60. test_sets.append((os.path.basename(file), tests))
  61. except IOError as err:
  62. sys.stderr.write("IOError reading \"" + file + "\" - " + str(err) + os.linesep)
  63. except xml.parsers.expat.ExpatError as err:
  64. sys.stderr.write("ExpatError reading \"" + file + "\" - " + str(err) + os.linesep)
  65. if not test_sets:
  66. continue
  67. # find matches
  68. setsCount = len(test_sets)
  69. test_cases = {}
  70. name_extractor = lambda name: str(name)
  71. for i in range(setsCount):
  72. for case in test_sets[i][1]:
  73. name = name_extractor(case)
  74. if name not in test_cases:
  75. test_cases[name] = [None] * setsCount
  76. test_cases[name][i] = case
  77. prevGroupName = None
  78. suit_time = 0
  79. suit_num = 0
  80. fails_num = 0
  81. for name in sorted(test_cases.keys(), key=alphanum_keyselector):
  82. cases = test_cases[name]
  83. groupName = next(c for c in cases if c).shortName()
  84. if groupName != prevGroupName:
  85. if prevGroupName != None:
  86. suit_time = suit_time/60 #from seconds to minutes
  87. testsuits.append({'module': module_name, 'name': prevGroupName, \
  88. 'time': suit_time, 'num': suit_num, 'failed': fails_num})
  89. overall_time += suit_time
  90. suit_time = 0
  91. suit_num = 0
  92. fails_num = 0
  93. prevGroupName = groupName
  94. for i in range(setsCount):
  95. case = cases[i]
  96. if not case is None:
  97. suit_num += 1
  98. if case.get('status') == 'run':
  99. suit_time += case.get('time')
  100. if case.get('status') == 'failed':
  101. fails_num += 1
  102. # last testsuit processing
  103. suit_time = suit_time/60
  104. testsuits.append({'module': module_name, 'name': prevGroupName, \
  105. 'time': suit_time, 'num': suit_num, 'failed': fails_num})
  106. overall_time += suit_time
  107. if len(testsuits)==0:
  108. exit(0)
  109. tbl = table()
  110. rows = 0
  111. if not options.failedOnly:
  112. tbl.newColumn('module', 'Module', align = 'left', cssclass = 'col_name')
  113. tbl.newColumn('name', 'Testsuit', align = 'left', cssclass = 'col_name')
  114. tbl.newColumn('time', 'Time (min)', align = 'center', cssclass = 'col_name')
  115. tbl.newColumn('num', 'Num of tests', align = 'center', cssclass = 'col_name')
  116. tbl.newColumn('failed', 'Failed', align = 'center', cssclass = 'col_name')
  117. # rows
  118. for suit in sorted(testsuits, key = lambda suit: suit['time'], reverse = True):
  119. tbl.newRow()
  120. tbl.newCell('module', suit['module'])
  121. tbl.newCell('name', suit['name'])
  122. tbl.newCell('time', formatValue(suit['time'], '', ''), suit['time'])
  123. tbl.newCell('num', suit['num'])
  124. if (suit['failed'] != 0):
  125. tbl.newCell('failed', suit['failed'])
  126. else:
  127. tbl.newCell('failed', ' ')
  128. rows += 1
  129. else:
  130. tbl.newColumn('module', 'Module', align = 'left', cssclass = 'col_name')
  131. tbl.newColumn('name', 'Testsuit', align = 'left', cssclass = 'col_name')
  132. tbl.newColumn('failed', 'Failed', align = 'center', cssclass = 'col_name')
  133. # rows
  134. for suit in sorted(testsuits, key = lambda suit: suit['time'], reverse = True):
  135. if (suit['failed'] != 0):
  136. tbl.newRow()
  137. tbl.newCell('module', suit['module'])
  138. tbl.newCell('name', suit['name'])
  139. tbl.newCell('failed', suit['failed'])
  140. rows += 1
  141. # output table
  142. if rows:
  143. if options.generateHtml:
  144. tbl.htmlPrintTable(sys.stdout)
  145. htmlPrintFooter(sys.stdout)
  146. else:
  147. if not options.failedOnly:
  148. print('\nOverall time: %.2f min\n' % overall_time)
  149. tbl.consolePrintTable(sys.stdout)
  150. print(2 * '\n')