summaryrefslogtreecommitdiffstats
path: root/bin/parse-perfcheck.py
diff options
context:
space:
mode:
Diffstat (limited to 'bin/parse-perfcheck.py')
-rwxr-xr-xbin/parse-perfcheck.py258
1 files changed, 258 insertions, 0 deletions
diff --git a/bin/parse-perfcheck.py b/bin/parse-perfcheck.py
new file mode 100755
index 000000000..158ef62fe
--- /dev/null
+++ b/bin/parse-perfcheck.py
@@ -0,0 +1,258 @@
+#!/usr/bin/python
+
+# This file is part of the LibreOffice project.
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import sys
+import os
+import getopt
+import csv
+
+
+colsResult = {}
+allTests = []
+
+def parseFile(dirname, filename, lastCommit):
+
+ curTestComment, total = None, None
+
+ path = os.path.join(dirname, filename)
+
+ trigger = "desc: Trigger: Client Request: "
+ trigger_len = len(trigger)
+ totals = "totals: "
+ totals_len = len(totals)
+
+ with open(path,'r') as callgrindFile:
+ lines = callgrindFile.readlines()
+
+ for line in lines:
+ if line.startswith(trigger):
+ curTestComment = line[trigger_len:].replace("\n","")
+ elif line.startswith(totals):
+ total = line[totals_len:].replace("\n","")
+
+ if curTestComment is None or total is None:
+ return None
+
+ testName = os.path.basename(dirname).replace(".test.core","")
+
+ lastCommitId, lastCommitDate = lastCommit
+ if lastCommitId not in colsResult:
+ colsResult[lastCommitId] = {}
+ colsResult[lastCommitId]['date'] = lastCommitDate
+ colsResult[lastCommitId]['values'] = {}
+
+ colsResult[lastCommitId]['values'][curTestComment] = total
+
+ return [lastCommitId, lastCommitDate, testName, curTestComment, total, filename]
+
+def processDirectory(rootDir, needsCsvHeader, lastCommit):
+
+ results = []
+
+ if needsCsvHeader:
+ results.append(["lastCommit", "lastCommitDate", "test filename", "dump comment", "count", "filename"])
+
+ for dirName, subdirList, fileList in os.walk(rootDir):
+ files = [f for f in fileList if f.startswith("callgrind.out.")]
+ for fname in files:
+ found = parseFile(dirName, fname, lastCommit)
+ if found is not None:
+ results.append(found)
+ return results
+
+def getLastCommitInfo():
+
+ stream = os.popen("git log --date=iso")
+ line = stream.readline()
+ commitId = line.replace("commit ","").replace("\n","")
+ line = stream.readline()
+ line = stream.readline()
+ commitDate = line.replace("Date: ","").replace("\n","").strip()
+
+ return commitId, commitDate
+
+def displayUsage():
+
+ usage = """
+
+Parses the callgrind results of make perfcheck
+
+Arguments :
+
+ --csv-file\t\t the target CSV file - new or containing previous tests - default : perfcheckResult.csv
+ --source-directory\t directory containing make perfcheck output - default : ./workdir/CppunitTest
+ --alert-type\t\t mode for calculating alerts - valid values : previous first
+ --alert-value\t\t alert threshold in % - default = 10
+
+ --help\t\t this message
+
+Columned output is dumped into csv-file + ".col"
+
+Alerts, if any, are displayed in standard output
+
+"""
+ print(usage)
+
+class WrongArguments(Exception):
+ pass
+
+def analyzeArgs(args):
+
+ try:
+ opts, args = getopt.getopt(args, 'x', [
+ 'csv-file=', 'source-directory=', 'alert-type=', 'alert-value=', 'help'])
+ except getopt.GetoptError:
+ raise WrongArguments
+
+ targetFileName = "perfcheckResult.csv"
+ sourceDirectory = "./workdir/CppunitTest"
+ alertType = ""
+ alertValue = 10
+
+ for o, a in opts:
+ if o == '--help':
+ displayUsage()
+ sys.exit()
+ elif o == "--csv-file":
+ targetFileName = a
+ elif o == "--source-directory":
+ sourceDirectory = a
+ elif o == "--alert-type":
+ alertType = a
+ elif o == "--alert-value":
+ alertValue = float(a)
+ else:
+ raise WrongArguments
+
+ return targetFileName, sourceDirectory, alertType, alertValue
+
+def readCsvFile(targetFilename):
+
+ with open(targetFilename, 'r') as csvfile:
+ reader = csv.reader(csvfile, delimiter="\t")
+ # skip header
+ next(reader)
+ for line in reader:
+
+ # do not process empty lines
+ if not line:
+ continue
+
+ curId, curDate, curTestName, curTestComment, curValue, currCallgrindFile = line
+
+ if curTestComment not in allTests:
+ allTests.append(curTestComment)
+
+ if curId not in colsResult:
+ colsResult[curId] = {}
+ colsResult[curId]['date'] = curDate
+ colsResult[curId]['values'] = {}
+
+ colsResult[curId]['values'][curTestComment] = curValue
+
+if __name__ == '__main__':
+
+ #check args
+ try:
+ targetFileName, sourceDirectory, alertType, alertValue = analyzeArgs(sys.argv[1:])
+ except WrongArguments:
+ displayUsage()
+ sys.exit(1)
+
+ # check if sourceDirectory exists
+ if not os.path.isdir(sourceDirectory):
+ print("sourceDirectory %s not found - Aborting" % (sourceDirectory))
+ sys.exit(1)
+
+ # read the complete CSV file
+ if os.path.isfile(targetFileName):
+ readCsvFile(targetFileName)
+ needsCsvHeader = False
+ else:
+ needsCsvHeader = True
+
+ # last commit Id
+ lastCommitId, lastCommitDate = getLastCommitInfo()
+
+ # walker through directory
+ if lastCommitId not in colsResult:
+
+ lastCommit = (lastCommitId, lastCommitDate)
+ results = processDirectory(sourceDirectory, needsCsvHeader, lastCommit)
+ ppResults = "\n".join(["\t".join(row) for row in results])
+
+ print('\nNew results\n' + ppResults)
+
+ # append raw result
+ with open(targetFileName,'a') as csvfile:
+ writer = csv.writer(csvfile, delimiter='\t')
+ writer.writerows(results)
+ print("\nCSV file written at " + targetFileName + '\n')
+
+ else:
+ print("\nCSV file up to date " + targetFileName + '\n')
+
+
+ # build columned output
+
+ # header
+ mLine = '\t'.join(["commit", "date"] + allTests) + '\n'
+
+ alertTest = {}
+
+ with open(targetFileName + '.col','w') as fileResult:
+ for k in colsResult:
+ mLine += k + "\t" + colsResult[k]['date'] + "\t"
+ for t in allTests:
+ if t in colsResult[k]['values']:
+ mValue= colsResult[k]['values'][t]
+ if t not in alertTest:
+ alertTest[t] = {}
+ alertTest[t][colsResult[k]['date']] = mValue
+ else:
+ mValue = ""
+ mLine += mValue + "\t"
+ mLine += "\n"
+
+ # write columned result
+ fileResult.write(mLine)
+
+ print("Columned file written at " + targetFileName + '.col\n')
+
+ # check for Alerts
+
+ if alertType == "":
+ sys.exit(1)
+
+ alertResult = ""
+
+ for t in alertTest:
+
+ testDict = alertTest[t]
+
+ # sort
+ keylist = sorted(testDict.keys())
+ maxVal = float(testDict[keylist[-1]])
+ minVal = 0
+
+ if alertType == "previous":
+ if len(keylist) > 1:
+ minVal = float(testDict[keylist[-2]])
+ else:
+ minVal = float(testDict[keylist[0]])
+
+ if minVal != 0:
+ delta = 100 * ((maxVal-minVal)/minVal)
+ else:
+ delta = 0
+
+ if delta > float(alertValue):
+ alertResult += t + "\t" + "{:.2f}".format(delta) + " %\n"
+
+ if alertResult != "":
+ print("!!!!!!!! ALERT !!!!!!!\n")
+ print(alertResult)