00001
00002 import os, time, sys, re, glob, exceptions
00003 import optparse as opt
00004 import cmsRelRegress as crr
00005 from cmsPerfCommons import Candles, KeywordToCfi, CandFname, cmsDriverPileUpOption, getVerFromLog
00006 import cmsRelValCmd,cmsCpuInfo
00007 import threading
00008 import subprocess
00009 import datetime
00010 import pickle
00011
00012
00013
00014
00015 def _cleanup():
00016 pass
00017
00018 subprocess._cleanup=_cleanup
00019
00020 class PerfThread(threading.Thread):
00021 def __init__(self,**args):
00022 self.args=args
00023 threading.Thread.__init__(self)
00024 def run(self):
00025 self.suite=PerfSuite()
00026
00027
00028
00029 self.suite.runPerfSuite(**(self.args))
00030
00031 class PerfSuiteTimer:
00032 """A class defining timing objects to time the running of the various parts of the performance suite. The class depends on module datetime."""
00033 def __init__(self,start=None):
00034 """Initialize the start time and set the end time to some indefinite time in the future"""
00035 self.start = start
00036 self.end = datetime.datetime.max
00037 self.duration = self.start - self.end
00038
00039
00040 def set_start(self,start=None):
00041 self.start = start
00042 def set_end(self,end=None):
00043
00044 self.end = end
00045 self.duration = self.end - self.start
00046
00047 def get_start(self):
00048 """Return the start time in ctime timestamp format"""
00049 return self.start.ctime()
00050 def get_end(self):
00051 """Return the end time in ctime timestamp format"""
00052 return self.end.ctime()
00053 def get_duration(self):
00054 """Return the duration between start and end as a dictionary with keys 'hours', 'minutes', 'seconds' to express the total duration in the favourite (most appropriate) unit. The function returns truncated integers."""
00055 self.duration_seconds = self.duration.days*86400 + self.duration.seconds
00056 self.duration_minutes = self.duration_seconds/60
00057 self.duration_hours = self.duration_seconds/3600
00058 return {'hours':self.duration_hours, 'minutes':self.duration_minutes, 'seconds':self.duration_seconds}
00059
00060 class PerfSuite:
00061 def __init__(self):
00062
00063 self.ERRORS = 0
00064 self._CASTOR_DIR = "/castor/cern.ch/cms/store/relval/performance/"
00065 self._dryrun = False
00066 self._debug = False
00067 self._unittest = False
00068 self._noexec = False
00069 self._verbose = True
00070 self.logh = sys.stdout
00071
00072
00073 try:
00074 self.cmssw_arch = os.environ["SCRAM_ARCH"]
00075 self.cmssw_version= os.environ["CMSSW_VERSION"]
00076 self.host = os.environ["HOST"]
00077 self.user = os.environ["USER"]
00078 except KeyError:
00079 self.logh.write('Error: An environment variable either SCRAM_ARCH, CMSSW_VERSION, HOST or USER is not available.\n')
00080 self.logh.write(' Please run eval `scramv1 runtime -csh` to set your environment variables\n')
00081 self.logh.flush()
00082 sys.exit()
00083
00084
00085 self.Scripts =["cmsDriver.py","cmsRelvalreport.py","cmsRelvalreportInput.py","cmsScimark2"]
00086 self.AuxiliaryScripts=["cmsScimarkLaunch.csh","cmsScimarkParser.py","cmsScimarkStop.py"]
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 class simpleGenReportThread(threading.Thread):
00107 def __init__(self,cpu,perfsuiteinstance,**simpleGenReportArgs):
00108 self.cpu=cpu
00109 self.simpleGenReportArgs=simpleGenReportArgs
00110 self.perfsuiteinstance=perfsuiteinstance
00111 threading.Thread.__init__(self)
00112 def run(self):
00113 self.PerfTest=self.perfsuiteinstance.PerfTest(self.cpu,self.perfsuiteinstance,**(self.simpleGenReportArgs))
00114 self.PerfTest.runPerfTest()
00115
00116 class PerfTest:
00117 def __init__(self,cpu,perfsuiteinstance,**simpleGenReportArgs):
00118 self.cpu=cpu
00119 self.simpleGenReportArgs=simpleGenReportArgs
00120 self.perfsuiteinstance=perfsuiteinstance
00121 def runPerfTest(self):
00122
00123
00124 if "--pileup" in self.simpleGenReportArgs['cmsdriverOptions']:
00125 self.perfsuiteinstance.logh.write("Launching the PILE UP %s tests on cpu %s with %s events each\n"%(self.simpleGenReportArgs['Name'],self.cpu,self.simpleGenReportArgs['NumEvents']))
00126 self.PerfTestPUTimer=PerfSuiteTimer(start=datetime.datetime.now())
00127 TimerInfo[self.simpleGenReportArgs['Name']].update({'PileUpTime':self.PerfTestPUTimer})
00128
00129 else:
00130 self.perfsuiteinstance.logh.write("Launching the %s tests on cpu %s with %s events each\n"%(self.simpleGenReportArgs['Name'],self.cpu,self.simpleGenReportArgs['NumEvents']))
00131 self.PerfTestTimer=PerfSuiteTimer(start=datetime.datetime.now())
00132 TimerInfo[self.simpleGenReportArgs['Name']].update({'NoPileUpTime':self.PerfTestTimer})
00133 self.perfsuiteinstance.logh.flush()
00134
00135 self.perfsuiteinstance.printDate()
00136 self.perfsuiteinstance.logh.flush()
00137 self.exitcode=self.perfsuiteinstance.simpleGenReport([self.cpu],**(self.simpleGenReportArgs))
00138
00139 if "--pileup" in self.simpleGenReportArgs['cmsdriverOptions']:
00140 self.PerfTestPUTimer.set_end(datetime.datetime.now())
00141 else:
00142 self.PerfTestTimer.set_end(datetime.datetime.now())
00143 return self.exitcode
00144
00145
00146 def optionParse(self,argslist=None):
00147 parser = opt.OptionParser(usage='''./cmsPerfSuite.py [options]
00148
00149 Examples:
00150
00151 cmsPerfSuite.py --step GEN-HLT -t 5 -i 2 -c 1 -m 5 --RunTimeSize MinBias,TTbar --RunIgProf TTbar --RunCallgrind TTbar --RunMemcheck TTbar --RunDigiPileUp TTbar --PUInputFile /store/relval/CMSSW_2_2_1/RelValMinBias/GEN-SIM-DIGI-RAW-HLTDEBUG/IDEAL_V9_v2/0001/101C84AF-56C4-DD11-A90D-001D09F24EC0.root --cmsdriver="--eventcontent FEVTDEBUGHLT --conditions FrontierConditions_GlobalTag,IDEAL_V9::All"
00152 (this will run the suite with 5 events for TimeSize tests on MinBias and TTbar, 2 for IgProf tests on TTbar only, 1 for Callgrind tests on TTbar only, 5 for Memcheck on MinBias and TTbar, it will also run DIGI PILEUP for all TTbar tests defined, i.e. 5 TimeSize, 2 IgProf, 1 Callgrind, 5 Memcheck. The file /store/relval/CMSSW_2_2_1/RelValMinBias/GEN-SIM-DIGI-RAW-HLTDEBUG/IDEAL_V9_v2/0001/101C84AF-56C4-DD11-A90D-001D09F24EC0.root will be copied locally as INPUT_PILEUP_EVENTS.root and it will be used as the input file for the MixingModule pile up events. All these tests will be done for the step GEN-HLT, i.e. GEN,SIM,DIGI,L1,DIGI2RAW,HLT at once)
00153 OR
00154 cmsPerfSuite.py --step GEN-HLT -t 5 -i 2 -c 1 -m 5 --RunTimeSize MinBias,TTbar --RunIgProf TTbar --RunCallgrind TTbar --RunMemcheck TTbar --RunTimeSizePU TTbar --PUInputFile /store/relval/CMSSW_2_2_1/RelValMinBias/GEN-SIM-DIGI-RAW-HLTDEBUG/IDEAL_V9_v2/0001/101C84AF-56C4-DD11-A90D-001D09F24EC0.root
00155 (this will run the suite with 5 events for TimeSize tests on MinBias and TTbar, 2 for IgProf tests on TTbar only, 1 for Callgrind tests on TTbar only, 5 for Memcheck on MinBias and TTbar, it will also run DIGI PILEUP on TTbar but only for 5 TimeSize events. All these tests will be done for the step GEN-HLT, i.e. GEN,SIM,DIGI,L1,DIGI2RAW,HLT at once)
00156 OR
00157 cmsPerfSuite.py --step GEN-HLT -t 5 -i 2 -c 1 -m 5 --RunTimeSize MinBias,TTbar --RunIgProf TTbar --RunCallgrind TTbar --RunMemcheck TTbar --RunTimeSizePU TTbar --PUInputFile /store/relval/CMSSW_2_2_1/RelValMinBias/GEN-SIM-DIGI-RAW-HLTDEBUG/IDEAL_V9_v2/0001/101C84AF-56C4-DD11-A90D-001D09F24EC0.root --cmsdriver="--eventcontent RAWSIM --conditions FrontierConditions_GlobalTag,IDEAL_V9::All"
00158 (this will run the suite with 5 events for TimeSize tests on MinBias and TTbar, 2 for IgProf tests on TTbar only, 1 for Callgrind tests on TTbar only, 5 for Memcheck on MinBias and TTbar, it will also run DIGI PILEUP on TTbar but only for 5 TimeSize events. All these tests will be done for the step GEN-HLT, i.e. GEN,SIM,DIGI,L1,DIGI2RAW,HLT at once. It will also add the options "--eventcontent RAWSIM --conditions FrontierConditions_GlobalTag,IDEAL_V9::All" to all cmsDriver.py commands executed by the suite. In addition it will run only 2 cmsDriver.py "steps": "GEN,SIM" and "DIGI". Note the syntax GEN-SIM for combined cmsDriver.py steps)
00159
00160 Legal entries for individual candles (--RunTimeSize, --RunIgProf, --RunCallgrind, --RunMemcheck options):
00161 %s
00162 ''' % ("\n".join(Candles)))
00163
00164 parser.set_defaults(TimeSizeEvents = 0 ,
00165 IgProfEvents = 0 ,
00166 CallgrindEvents = 0 ,
00167 MemcheckEvents = 0 ,
00168 cmsScimark = 10 ,
00169 cmsScimarkLarge = 10 ,
00170 cmsdriverOptions = "--eventcontent FEVTDEBUGHLT",
00171
00172 stepOptions = "" ,
00173 profilers = "" ,
00174 outputdir = "" ,
00175 logfile = os.path.join(os.getcwd(),"cmsPerfSuite.log"),
00176 runonspare = True ,
00177 bypasshlt = False ,
00178 quicktest = False ,
00179 unittest = False ,
00180 noexec = False ,
00181 dryrun = False ,
00182 verbose = True ,
00183 previousrel = "" ,
00184 castordir = self._CASTOR_DIR,
00185 cores = cmsCpuInfo.get_NumOfCores(),
00186 cpu = "1" ,
00187 RunTimeSize = "" ,
00188 RunIgProf = "" ,
00189 RunCallgrind = "" ,
00190 RunMemcheck = "" ,
00191 RunDigiPileUP = "" ,
00192 RunTimeSizePU = "" ,
00193 RunIgProfPU = "" ,
00194 RunCallgrindPU = "" ,
00195 RunMemcheckPU = "" ,
00196 PUInputFile = "" ,
00197 userInputFile = "" )
00198 parser.add_option('-q', '--quiet' , action="store_false", dest='verbose' ,
00199 help = 'Output less information' )
00200 parser.add_option('-b', '--bypass-hlt' , action="store_true" , dest='bypasshlt' ,
00201 help = 'Bypass HLT root file as input to RAW2DIGI')
00202 parser.add_option('-n', '--notrunspare', action="store_false", dest='runonspare',
00203 help = 'Do not run cmsScimark on spare cores')
00204 parser.add_option('-t', '--timesize' , type='int' , dest='TimeSizeEvents' , metavar='<#EVENTS>' ,
00205 help = 'specify the number of events for the TimeSize tests' )
00206 parser.add_option('-i', '--igprof' , type='int' , dest='IgProfEvents' , metavar='<#EVENTS>' ,
00207 help = 'specify the number of events for the IgProf tests' )
00208 parser.add_option('-c', '--callgrind' , type='int' , dest='CallgrindEvents' , metavar='<#EVENTS>' ,
00209 help = 'specify the number of events for the Callgrind tests' )
00210 parser.add_option('-m', '--memcheck' , type='int' , dest='MemcheckEvents' , metavar='<#EVENTS>' ,
00211 help = 'specify the number of events for the Memcheck tests' )
00212 parser.add_option('--cmsScimark' , type='int' , dest='cmsScimark' , metavar='' ,
00213 help = 'specify the number of times the cmsScimark benchmark is run before and after the performance suite on cpu1')
00214 parser.add_option('--cmsScimarkLarge' , type='int' , dest='cmsScimarkLarge' , metavar='' ,
00215 help = 'specify the number of times the cmsScimarkLarge benchmark is run before and after the performance suite on cpu1')
00216 parser.add_option('--cores' , type='int', dest='cores' , metavar='<CORES>' ,
00217 help = 'specify the number of cores of the machine (can be used with 0 to stop cmsScimark from running on the other cores)')
00218 parser.add_option('--cmsdriver' , type='string', dest='cmsdriverOptions', metavar='<OPTION_STR>',
00219 help = 'specify special options to use with the cmsDriver.py commands (designed for integration build use')
00220 parser.add_option('-a', '--archive' , type='string', dest='castordir' , metavar='<DIR>' ,
00221 help = 'specify the wanted CASTOR directory where to store the results tarball')
00222 parser.add_option('-L', '--logfile' , type='string', dest='logfile' , metavar='<FILE>' ,
00223 help = 'file to store log output of the script')
00224 parser.add_option('-o', '--output' , type='string', dest='outputdir' , metavar='<DIR>' ,
00225 help = 'specify the directory where to store the output of the script')
00226 parser.add_option('-r', '--prevrel' , type='string', dest='previousrel' , metavar='<DIR>' ,
00227 help = 'Top level dir of previous release for regression analysis')
00228 parser.add_option('--step' , type='string', dest='stepOptions' , metavar='<STEPS>' ,
00229 help = 'specify the processing steps intended (instead of the default ones)' )
00230 parser.add_option('--cpu' , type='string', dest='cpu' , metavar='<CPU>' ,
00231 help = 'specify the core on which to run the performance suite')
00232
00233
00234 parser.add_option('--RunTimeSize' , type='string', dest='RunTimeSize' , metavar='<CANDLES>' ,
00235 help = 'specify on which candles to run the TimeSize tests')
00236 parser.add_option('--RunIgProf' , type='string', dest='RunIgProf' , metavar='<CANDLES>' ,
00237 help = 'specify on which candles to run the IgProf tests')
00238 parser.add_option('--RunCallgrind' , type='string', dest='RunCallgrind' , metavar='<CANDLES>' ,
00239 help = 'specify on which candles to run the Callgrind tests')
00240 parser.add_option('--RunMemcheck' , type='string', dest='RunMemcheck' , metavar='<CANDLES>' ,
00241 help = 'specify on which candles to run the Memcheck tests')
00242 parser.add_option('--RunDigiPileUp' , type='string', dest='RunDigiPileUp' , metavar='<CANDLES>' ,
00243 help = 'specify the candle on which to run DIGI PILE UP and repeat all the tests set to run on that candle with PILE UP')
00244 parser.add_option('--PUInputFile' , type='string', dest='PUInputFile' , metavar='<FILE>' ,
00245 help = 'specify the root file to pick the pile-up events from')
00246 parser.add_option('--RunTimeSizePU' , type='string', dest='RunTimeSizePU' , metavar='<CANDLES>' ,
00247 help = 'specify on which candles to run the TimeSize tests with PILE UP')
00248 parser.add_option('--RunIgProfPU' , type='string', dest='RunIgProfPU' , metavar='<CANDLES>' ,
00249 help = 'specify on which candles to run the IgProf tests with PILE UP')
00250 parser.add_option('--RunCallgrindPU' , type='string', dest='RunCallgrindPU' , metavar='<CANDLES>' ,
00251 help = 'specify on which candles to run the Callgrind tests with PILE UP')
00252 parser.add_option('--RunMemcheckPU' , type='string', dest='RunMemcheckPU' , metavar='<CANDLES>' ,
00253 help = 'specify on which candles to run the Memcheck tests with PILE UP')
00254
00255
00256 parser.add_option('--filein' , type='string', dest='userInputFile' , metavar='<FILE>',
00257 help = 'specify input RAW root file for HLT and RAW2DIGI-RECO (list the files in the same order as the candles for the tests)')
00258
00259
00260 parser.add_option('--mail', type='string', dest='MailLogRecipients', metavar='<EMAIL ADDRESS>', default=self.user, help='specify valid email address(es) name@domain in order to receive notification at the end of the performance suite running with the cmsPerfSuite.log file')
00261
00262
00263 parser.add_option('--no_tarball', action="store_false", dest='tarball', default=True, help='Turn off automatic tarball creation at the end of the performance suite execution')
00264
00265
00266
00267
00268
00269
00270 devel = opt.OptionGroup(parser, "Developer Options",
00271 "Caution: use these options at your own risk."
00272 "It is believed that some of them bite.\n")
00273
00274 devel.add_option('-p', '--profile' , type="str" , dest='profilers', metavar="<PROFILERS>" ,
00275 help = 'Profile codes to use for cmsRelvalInput' )
00276 devel.add_option('-f', '--false-run', action="store_true", dest='dryrun' ,
00277 help = 'Dry run' )
00278 devel.add_option('-d', '--debug' , action='store_true', dest='debug' ,
00279 help = 'Debug' )
00280 devel.add_option('--quicktest' , action="store_true", dest='quicktest',
00281 help = 'Quick overwrite all the defaults to small numbers so that we can run a quick test of our chosing.' )
00282 devel.add_option('--test' , action="store_true", dest='unittest' ,
00283 help = 'Perform a simple test, overrides other options. Overrides verbosity and sets it to false.' )
00284 devel.add_option('--no_exec' , action="store_true", dest='noexec' ,
00285 help = 'Run the suite without executing the cmsRelvalreport.py commands in the various directories. This is a useful debugging tool.' )
00286 parser.add_option_group(devel)
00287 (options, args) = parser.parse_args(argslist)
00288
00289
00290 self._debug = options.debug
00291 self._unittest = options.unittest
00292 self._noexec = options.noexec
00293 self._verbose = options.verbose
00294 self._dryrun = options.dryrun
00295 castordir = options.castordir
00296 TimeSizeEvents = options.TimeSizeEvents
00297 IgProfEvents = options.IgProfEvents
00298 CallgrindEvents = options.CallgrindEvents
00299 MemcheckEvents = options.MemcheckEvents
00300 cmsScimark = options.cmsScimark
00301 cmsScimarkLarge = options.cmsScimarkLarge
00302 cmsdriverOptions = options.cmsdriverOptions
00303 stepOptions = options.stepOptions
00304 quicktest = options.quicktest
00305
00306 runonspare = options.runonspare
00307 profilers = options.profilers.strip()
00308 cpu = options.cpu.strip()
00309 bypasshlt = options.bypasshlt
00310 cores = options.cores
00311 logfile = options.logfile
00312 prevrel = options.previousrel
00313 outputdir = options.outputdir
00314 RunTimeSize = options.RunTimeSize
00315 RunIgProf = options.RunIgProf
00316 RunCallgrind = options.RunCallgrind
00317 RunMemcheck = options.RunMemcheck
00318 RunDigiPileUp = options.RunDigiPileUp
00319 RunTimeSizePU = options.RunTimeSizePU
00320 RunIgProfPU = options.RunIgProfPU
00321 RunCallgrindPU = options.RunCallgrindPU
00322 RunMemcheckPU = options.RunMemcheckPU
00323 PUInputFile = options.PUInputFile
00324 userInputFile = options.userInputFile
00325 if options.MailLogRecipients !="" and self.user not in options.MailLogRecipients:
00326 MailLogRecipients= self.user+","+options.MailLogRecipients
00327 else:
00328 MailLogRecipients=options.MailLogRecipients
00329 tarball = options.tarball
00330
00331
00332
00333
00334 if not logfile == None:
00335 logfile = os.path.abspath(logfile)
00336 logdir = os.path.dirname(logfile)
00337 if not os.path.exists(logdir):
00338 parser.error("Directory to output logfile does not exist")
00339 sys.exit()
00340 logfile = os.path.abspath(logfile)
00341
00342
00343
00344
00345 if "GEN,SIM" in stepOptions:
00346 self.logh.write("WARNING: Please use GEN-SIM with a hypen not a \",\"!\n")
00347
00348
00349 if stepOptions == "" or stepOptions == 'Default':
00350 pass
00351 else:
00352 stepOptions='--usersteps=%s' % (stepOptions)
00353
00354
00355
00356
00357 isnumreg = re.compile("^-?[0-9]*$")
00358 found = isnumreg.search(profilers)
00359 if not found :
00360 parser.error("profile codes option contains non-numbers")
00361 sys.exit()
00362
00363
00364
00365
00366 if outputdir == "":
00367 outputdir = os.getcwd()
00368 else:
00369 outputdir = os.path.abspath(outputdir)
00370
00371 if not os.path.isdir(outputdir):
00372 parser.error("%s is not a valid output directory" % outputdir)
00373 sys.exit()
00374
00375
00376
00377
00378 numetcomreg = re.compile("^[0-9,]*")
00379 if not numetcomreg.search(cpu):
00380 parser.error("cpu option needs to be a comma separted list of ints or a single int")
00381 sys.exit()
00382
00383 cpustr = cpu
00384 cpu = []
00385 if "," in cpustr:
00386 cpu = map(lambda x: int(x),cpustr.split(","))
00387 else:
00388 cpu = [ int(cpustr) ]
00389
00390
00391
00392
00393 if not prevrel == "":
00394 prevrel = os.path.abspath(prevrel)
00395 if not os.path.exists(prevrel):
00396 self.logh.write("ERROR: Previous release dir %s could not be found" % prevrel)
00397 sys.exit()
00398
00399
00400
00401
00402 if quicktest:
00403 TimeSizeEvents = 1
00404 IgProfEvents = 1
00405 CallgrindEvents = 0
00406 MemcheckEvents = 0
00407 cmsScimark = 1
00408 cmsScimarkLarge = 1
00409
00410
00411
00412
00413 if self._unittest:
00414 self._verbose = False
00415 if stepOptions == "":
00416 stepOptions = "GEN-SIM,DIGI,L1,DIGI2RAW,HLT,RAW2DIGI-RECO"
00417 cmsScimark = 0
00418 cmsScimarkLarge = 0
00419 CallgrindEvents = 0
00420 MemcheckEvents = 0
00421 IgProfEvents = 0
00422 TimeSizeEvents = 1
00423
00424
00425 TimeSizeCandles=[]
00426 IgProfCandles=[]
00427 CallgrindCandles=[]
00428 MemcheckCandles=[]
00429 TimeSizePUCandles=[]
00430 IgProfPUCandles=[]
00431 CallgrindPUCandles=[]
00432 MemcheckPUCandles=[]
00433 userInputRootFiles=[]
00434 if RunTimeSize:
00435 TimeSizeCandles = RunTimeSize.split(",")
00436 if RunIgProf:
00437 IgProfCandles = RunIgProf.split(",")
00438 if RunCallgrind:
00439 CallgrindCandles = RunCallgrind.split(",")
00440 if RunMemcheck:
00441 MemcheckCandles = RunMemcheck.split(",")
00442 if RunDigiPileUp:
00443 for candle in RunDigiPileUp.split(","):
00444 if candle in TimeSizeCandles:
00445 TimeSizePUCandles.append(candle)
00446 if candle in IgProfCandles:
00447 IgProfPUCandles.append(candle)
00448 if candle in CallgrindCandles:
00449 CallgrindPUCandles.append(candle)
00450 if candle in MemcheckCandles:
00451 MemcheckPUCandles.append(candle)
00452 if RunTimeSizePU:
00453 TimeSizePUCandles.extend(RunTimeSizePU.split(","))
00454
00455 temp=set(TimeSizePUCandles)
00456 TimeSizePUCandles=list(temp)
00457 if RunIgProfPU:
00458 IgProfPUCandles.extend(RunIgProfPU.split(","))
00459
00460 temp=set(IgProfPUCandles)
00461 IgProfPUCandles=list(temp)
00462 if RunCallgrindPU:
00463 CallgrindPUCandles.extend(RunCallgrindPU.split(","))
00464
00465 temp=set(CallgrindPUCandles)
00466 CallgrindPUCandles=list(temp)
00467 if RunMemcheckPU:
00468 MemcheckPUCandles.extend(RunMemcheckPU.split(","))
00469
00470 temp=set(MemcheckPUCandles)
00471 MemcheckPUCandles=list(temp)
00472 if userInputFile:
00473 userInputRootFiles=userInputFile.split(",")
00474
00475
00476
00477
00478
00479
00480 cmsdriverPUOptions=""
00481 if cmsdriverOptions:
00482
00483 if TimeSizePUCandles or IgProfPUCandles or CallgrindPUCandles or MemcheckPUCandles:
00484
00485 cmsdriverPUOptions = '--cmsdriver="%s %s%s"'%(cmsdriverOptions," --pileup=",cmsDriverPileUpOption)
00486
00487 cmsdriverOptions = '--cmsdriver="%s"'%cmsdriverOptions
00488
00489 return (castordir ,
00490 TimeSizeEvents ,
00491 IgProfEvents ,
00492 CallgrindEvents ,
00493 MemcheckEvents ,
00494 cmsScimark ,
00495 cmsScimarkLarge ,
00496 cmsdriverOptions,
00497 cmsdriverPUOptions,
00498 stepOptions ,
00499 quicktest ,
00500 profilers ,
00501 cpu ,
00502 cores ,
00503 prevrel ,
00504 bypasshlt ,
00505 runonspare ,
00506 outputdir ,
00507 logfile ,
00508 TimeSizeCandles ,
00509 IgProfCandles ,
00510 CallgrindCandles,
00511 MemcheckCandles ,
00512 TimeSizePUCandles ,
00513 IgProfPUCandles ,
00514 CallgrindPUCandles,
00515 MemcheckPUCandles ,
00516 PUInputFile ,
00517 userInputRootFiles,
00518 MailLogRecipients,
00519 tarball)
00520
00521
00522
00523
00524
00525
00526
00527 def runCmdSet(self,cmd):
00528 exitstat = 0
00529 if len(cmd) <= 1:
00530 exitstat = self.runcmd(cmd)
00531 if self._verbose:
00532 self.printFlush(cmd)
00533 else:
00534 for subcmd in cmd:
00535 if self._verbose:
00536 self.printFlush(subcmd)
00537 exitstat = self.runcmd(" && ".join(cmd))
00538 if self._verbose:
00539 self.printFlush(self.getDate())
00540 return exitstat
00541
00542
00543
00544
00545 def printFlush(self,command):
00546 if self._verbose:
00547 self.logh.write(str(command) + "\n")
00548 self.logh.flush()
00549
00550
00551
00552
00553 def runcmd(self,command):
00554
00555
00556
00557
00558
00559 try:
00560 process = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
00561 pid=process.pid
00562 exitstat= process.wait()
00563 cmdout = process.stdout.read()
00564 exitstat = process.returncode
00565 except OSError, detail:
00566 self.logh.write("Race condition in subprocess.Popen has robbed us of the exit code of the %s process (PID %s).Assume it failed!\n %s\n"%(command,pid,detail))
00567 self.logh.flush()
00568 exitstat=999
00569 cmdout="Race condition in subprocess.Popen has robbed us of the exit code of the %s process (PID %s).Assume it failed!\n %s"%(command,pid,detail)
00570 if self._verbose:
00571 self.logh.write(cmdout)
00572 self.logh.flush()
00573 if exitstat == None:
00574 self.logh.write("Something strange is going on! Exit code was None for command %s: check if it really ran!"%command)
00575 self.logh.flush()
00576 exitstat=0
00577 return exitstat
00578
00579 def getDate(self):
00580 return time.ctime()
00581
00582 def printDate(self):
00583 self.logh.write(self.getDate() + "\n")
00584 self.logh.flush()
00585
00586
00587
00588 def mkCandleDir(self,pfdir,candle,profiler):
00589 adir = os.path.join(pfdir,"%s_%s" % (candle,profiler))
00590 self.runcmd( "mkdir -p %s" % adir )
00591 if self._verbose:
00592 self.printDate()
00593 return adir
00594
00595
00596
00597
00598
00599 def cprootfile(self,dir,candle,NumOfEvents,cmsdriverOptions=""):
00600 cmds = ("cd %s" % dir,
00601 "cp -pR ../%s_IgProf/%s_GEN,SIM.root ." % (candle,CandFname[candle]))
00602
00603 if self.runCmdSet(cmds):
00604 self.logh.write("Since there was no ../%s_IgProf/%s_GEN,SIM.root file it will be generated first\n"%(candle,CandFname[candle]))
00605
00606 cmd = "cd %s ; cmsDriver.py %s -s GEN,SIM -n %s --fileout %s_GEN,SIM.root %s>& %s_GEN_SIM_for_valgrind.log" % (dir,KeywordToCfi[candle],str(NumOfEvents),candle,cmsdriverOptions,candle)
00607
00608 self.printFlush(cmd)
00609
00610
00611 cmdout=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read()
00612 if cmdout:
00613 self.printFlush(cmdout)
00614 return cmdout
00615
00616
00617
00618
00619 def displayErrors(self,file):
00620 try:
00621 for line in open(file,"r"):
00622 if "cerr" in line or "CMSException" in line:
00623 self.logh.write("ERROR: %s\n" % line)
00624 self.ERRORS += 1
00625 except OSError, detail:
00626 self.logh.write("WARNING: %s\n" % detail)
00627 self.ERRORS += 1
00628 except IOError, detail:
00629 self.logh.write("WARNING: %s\n" % detail)
00630 self.ERRORS += 1
00631
00632
00633
00634
00635 def valFilterReport(self,dir):
00636
00637
00638
00639
00640
00641 InputFileName=os.path.join(dir,"SimulationCandles_%s.txt"%(self.cmssw_version))
00642 InputFile=open(InputFileName,"r")
00643 InputLines=InputFile.readlines()
00644 InputFile.close()
00645 Outputfile=open(InputFileName,"w")
00646 simRegxp=re.compile("step=GEN,SIM")
00647 digiRegxp=re.compile("step=DIGI")
00648 CallgrindRegxp=re.compile("ValgrindFCE")
00649 MemcheckRegxp=re.compile("Memcheck")
00650 NumEvtRegxp=re.compile("-n 1")
00651 for line in InputLines:
00652 if simRegxp.search(line) and CallgrindRegxp.search(line):
00653 continue
00654 elif simRegxp.search(line) and MemcheckRegxp.search(line):
00655
00656 if NumEvtRegxp.search(line):
00657 line=NumEvtRegxp.sub(r"-n 5",line)
00658 else:
00659 self.logh.write("The number of Memcheck event was not changed since the original number of Callgrind event was not 1!\n")
00660 Outputfile.write(line)
00661 elif digiRegxp.search(line) and MemcheckRegxp.search(line):
00662
00663 if NumEvtRegxp.search(line):
00664 line=NumEvtRegxp.sub(r"-n 5",line)
00665 else:
00666 self.logh.write("The number of Memcheck event was not changed since the original number of Callgrind event was not 1!\n")
00667 Outputfile.write(line)
00668 else:
00669 Outputfile.write(line)
00670 self.logh.flush()
00671 Outputfile.close()
00672
00673
00674
00675
00676
00677
00678 def benchmarks(self,cpu,pfdir,name,bencher,large=False):
00679 cmd = self.Commands[cpu][3]
00680 redirect = ""
00681 if large:
00682 redirect = " -large >>"
00683 else:
00684 redirect = " >>"
00685
00686 for i in range(bencher):
00687
00688 if not os.path.exists(os.path.join(pfdir,os.path.basename(name))):
00689
00690 open(os.path.join(pfdir,os.path.basename(name)))
00691
00692 command= cmd + redirect + os.path.join(pfdir,os.path.basename(name))
00693 self.printFlush(command + " [%s/%s]" % (i+1,bencher))
00694 self.runcmd(command)
00695 self.logh.flush()
00696
00697
00698
00699
00700 def runCmsReport(self,cpu,dir,candle):
00701 cmd = self.Commands[cpu][1]
00702 cmds = ("cd %s" % (dir),
00703 "%s -i SimulationCandles_%s.txt -t perfreport_tmp -R -P >& %s.log" % (cmd,self.cmssw_version,candle))
00704 exitstat = 0
00705 if not self._debug:
00706 exitstat = self.runCmdSet(cmds)
00707
00708 if self._unittest and (not exitstat == 0):
00709 self.logh.write("ERROR: CMS Report returned a non-zero exit status \n")
00710 sys.exit(exitstat)
00711 else:
00712 return(exitstat)
00713
00714
00715
00716
00717 def testCmsDriver(self,cpu,dir,cmsver,candle):
00718 cmsdrvreg = re.compile("^cmsDriver.py")
00719 cmd = self.Commands[cpu][0]
00720 noExit = True
00721 stepreg = re.compile("--step=([^ ]*)")
00722 previousCmdOnline = ""
00723 for line in open(os.path.join(dir,"SimulationCandles_%s.txt" % (cmsver))):
00724 if (not line.lstrip().startswith("#")) and not (line.isspace() or len(line) == 0):
00725 cmdonline = line.split("@@@",1)[0]
00726 if cmsdrvreg.search(cmdonline) and not previousCmdOnline == cmdonline:
00727 stepbeingrun = "Unknown"
00728 matches = stepreg.search(cmdonline)
00729 if not matches == None:
00730 stepbeingrun = matches.groups()[0]
00731 if "PILEUP" in cmdonline:
00732 stepbeingrun += "_PILEUP"
00733 self.logh.write(cmdonline + "\n")
00734 cmds = ("cd %s" % (dir),
00735 "%s >& ../cmsdriver_unit_test_%s_%s.log" % (cmdonline,candle,stepbeingrun))
00736 if self._dryrun:
00737 self.logh.write(cmds + "\n")
00738 else:
00739 out = self.runCmdSet(cmds)
00740 if not out == None:
00741 sig = out >> 16
00742 xstatus = out & 0xffff
00743 self.logh.write("FATAL ERROR: CMS Driver returned a non-zero exit status (which is %s) when running %s for candle %s. Signal interrupt was %s\n" % (xstatus,stepbeingrun,candle,sig))
00744 sys.exit()
00745 previousCmdOnline = cmdonline
00746
00747
00748
00749
00750 def runCmsInput(self,cpu,dir,numevents,candle,cmsdrvopts,stepopt,profiles,bypasshlt,userInputFile):
00751
00752
00753 bypass = ""
00754 if bypasshlt:
00755 bypass = "--bypass-hlt"
00756 userInputFileOption=""
00757 if userInputFile:
00758 userInputFileOption = "--filein %s"%userInputFile
00759 cmd = self.Commands[cpu][2]
00760 cmds=[]
00761
00762 cmds = ("cd %s" % (dir),
00763 "%s %s \"%s\" %s %s %s %s %s" % (cmd,
00764 numevents,
00765 candle,
00766 profiles,
00767 cmsdrvopts,
00768 stepopt,
00769 bypass,userInputFileOption))
00770 exitstat=0
00771 exitstat = self.runCmdSet(cmds)
00772 if self._unittest and (not exitstat == 0):
00773 self.logh.write("ERROR: CMS Report Input returned a non-zero exit status \n" )
00774 return exitstat
00775
00776
00777
00778
00779 def simpleGenReport(self,cpus,perfdir=os.getcwd(),NumEvents=1,candles=['MinBias'],cmsdriverOptions='',stepOptions='',Name='',profilers='',bypasshlt='',userInputRootFiles=''):
00780 callgrind = Name == "Callgrind"
00781 memcheck = Name == "Memcheck"
00782
00783 profCodes = {"TimeSize" : "0123",
00784 "IgProf" : "4567",
00785 "IgProf_Perf":"47",
00786 "IgProf_Mem":"567",
00787 "Callgrind": "8",
00788 "Memcheck" : "9",
00789 None : "-1"}
00790
00791 profiles = profCodes[Name]
00792 if not profilers == "":
00793 profiles = profilers
00794
00795 RelvalreportExitCode=0
00796
00797 for cpu in cpus:
00798 pfdir = perfdir
00799 if len(cpus) > 1:
00800 pfdir = os.path.join(perfdir,"cpu_%s" % cpu)
00801 for candle in candles:
00802
00803
00804 if "--pileup" in cmsdriverOptions:
00805 candlename=candle+"_PU"
00806 else:
00807 candlename=candle
00808 adir=self.mkCandleDir(pfdir,candlename,Name)
00809 if self._unittest:
00810
00811 if userInputRootFiles:
00812 self.logh.write(userInputRootFiles)
00813 userInputFile=userInputRootFiles[0]
00814 else:
00815 userInputFile=""
00816 self.logh.flush()
00817 self.runCmsInput(cpu,adir,NumEvents,candle,cmsdriverOptions,stepOptions,profiles,bypasshlt,userInputFile)
00818 self.testCmsDriver(cpu,adir,candle)
00819 else:
00820 if userInputRootFiles:
00821 self.logh.write("Variable userInputRootFiles is %s\n"%userInputRootFiles)
00822
00823
00824
00825
00826
00827
00828 userInputFile=""
00829 candleregexp=re.compile(candle)
00830 for file in userInputRootFiles:
00831 if candleregexp.search(file):
00832 userInputFile=file
00833 self.logh.write("For these %s %s tests will use user input file %s\n"%(candlename,Name,userInputFile))
00834 if userInputFile == "":
00835 self.logh.write("***WARNING: For these %s %s tests could not find a matching input file in %s: will try to do without it!!!!!\n"%(candlename,Name,userInputRootFiles))
00836 self.logh.flush()
00837 else:
00838 userInputFile=""
00839 DummyTestName=candlename+"_"+stepOptions.split("=")[1]
00840 DummyTimer=PerfSuiteTimer(start=datetime.datetime.now())
00841 TimerInfo[Name].update({DummyTestName:DummyTimer})
00842
00843 self.runCmsInput(cpu,adir,NumEvents,candle,cmsdriverOptions,stepOptions,profiles,bypasshlt,userInputFile)
00844
00845 if self._noexec:
00846 self.logh.write("Running in debugging mode, without executing cmsRelvalreport.py\n")
00847 self.logh.flush()
00848 pass
00849 else:
00850
00851 ExitCode=self.runCmsReport(cpu,adir,candle)
00852 self.logh.write("Individual cmsRelvalreport.py ExitCode %s\n"%ExitCode)
00853 RelvalreportExitCode=RelvalreportExitCode+ExitCode
00854 self.logh.write("Summed cmsRelvalreport.py ExitCode %s\n"%RelvalreportExitCode)
00855 self.logh.flush()
00856 DummyTimer.set_end(datetime.datetime.now())
00857
00858
00859
00860
00861 globpath = os.path.join(adir,"*.log")
00862 self.logh.write("Looking for logs that match %s\n" % globpath)
00863 logs = glob.glob(globpath)
00864 for log in logs:
00865 self.logh.write("Found log %s\n" % log)
00866 self.displayErrors(log)
00867 self.printFlush("Returned cumulative RelvalreportExitCode is %s"%RelvalreportExitCode)
00868 return RelvalreportExitCode
00869
00870
00871
00872
00873
00874
00875
00876
00877 def runPerfSuite(self,
00878 castordir = "/castor/cern.ch/cms/store/relval/performance/",
00879 TimeSizeEvents = 100 ,
00880 IgProfEvents = 5 ,
00881 CallgrindEvents = 1 ,
00882 MemcheckEvents = 5 ,
00883 cmsScimark = 10 ,
00884 cmsScimarkLarge = 10 ,
00885 cmsdriverOptions = "" ,
00886 cmsdriverPUOptions= "" ,
00887 stepOptions = "" ,
00888 quicktest = False ,
00889 profilers = "" ,
00890 cpus = [1] ,
00891 cores = 4 ,
00892 prevrel = "" ,
00893 bypasshlt = False ,
00894 runonspare = True ,
00895 perfsuitedir = os.getcwd(),
00896 logfile = None,
00897 TimeSizeCandles = "" ,
00898 IgProfCandles = "" ,
00899 CallgrindCandles = "" ,
00900 MemcheckCandles = "" ,
00901 TimeSizePUCandles = "" ,
00902 IgProfPUCandles = "" ,
00903 CallgrindPUCandles = "" ,
00904 MemcheckPUCandles = "" ,
00905 PUInputFile = "" ,
00906 userInputFile = "" ,
00907 MailLogRecipients = "" ,
00908 tarball = "" ):
00909
00910
00911 FinalExitCode=0
00912
00913
00914 if not logfile == None:
00915 try:
00916 self.logh = open(logfile,"a")
00917 except (OSError, IOError), detail:
00918 self.logh.write(detail + "\n")
00919 self.logh.flush()
00920
00921
00922 self.HEPSPEC06 = 0
00923 try:
00924 HEPSPEC06_file=open("/build/HEPSPEC06.score","r")
00925 for line in HEPSPEC06_file.readlines():
00926 if not line.startswith("#") and "HEPSPEC06" in line:
00927 self.HEPSPEC06= line.split()[2]
00928 except IOError:
00929 self.logh.write("***Warning***: Could not find file /build/HEPSPEC06.score file on this machine!\n")
00930 self.logh.flush()
00931
00932
00933 localcpuinfo=os.path.join(perfsuitedir,"cpuinfo")
00934 cpuinfo_exitcode=-1
00935 if os.path.exists(localcpuinfo):
00936 cpuinfo_exitcode=0
00937 else:
00938 self.logh.write("Copying /proc/cpuinfo in current working directory (%s)\n"%perfsuitedir)
00939 cpuinfo_exitcode=self.runcmd("cp /proc/cpuinfo %s"%perfsuitedir)
00940 localmeminfo=os.path.join(perfsuitedir,"meminfo")
00941 meminfo_exitcode=-1
00942 if os.path.exists(localmeminfo):
00943 meminfo_exitcode=0
00944 else:
00945 self.logh.write("Copying /proc/meminfo in current working directory (%s)\n"%perfsuitedir)
00946 meminfo_exitcode=self.runcmd("cp /proc/meminfo %s"%perfsuitedir)
00947 if cpuinfo_exitcode or meminfo_exitcode:
00948 self.logh.write("There was an issue copying the cpuinfo or meminfo files!\n")
00949 self.logh.flush()
00950
00951 try:
00952 if not prevrel == "":
00953 self.logh.write("Production of regression information has been requested with release directory %s\n" % prevrel)
00954 if not cmsdriverOptions == "":
00955 self.logh.write("Running cmsDriver.py with user defined options: %s\n" % cmsdriverOptions)
00956
00957 cmsdriverOptionsRelvalInput="--cmsdriver="+cmsdriverOptions
00958
00959 if not stepOptions == "":
00960 self.logh.write("Running user defined steps only: %s\n" % stepOptions)
00961
00962 setpOptionsRelvalInput="--usersteps="+stepOptions
00963
00964 if bypasshlt:
00965
00966 bypasshltRelvalInput="--bypass-hlt"
00967
00968 self.logh.write("Current Architecture is %s\n"%self.cmssw_arch)
00969 self.logh.write("Current CMSSW version is %s\n"%self.cmssw_version)
00970 self.logh.write("This machine ( %s ) is assumed to have %s cores, and the suite will be run on cpu %s\n" %(self.host,cores,cpus))
00971 self.logh.write("This machine's HEPSPEC06 score is: %s \n"%self.HEPSPEC06)
00972 path=os.path.abspath(".")
00973 self.logh.write("Performance Suite started running at %s on %s in directory %s, run by user %s\n" % (self.getDate(),self.host,path,self.user))
00974
00975 TotalTime=PerfSuiteTimer(start=datetime.datetime.now())
00976
00977 global TimerInfo
00978 TimerInfo={'TotalTime':{'TotalTime':TotalTime}}
00979
00980
00981 showtags=subprocess.Popen("showtags -r",shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read()
00982 self.logh.write(showtags)
00983 self.logh.flush()
00984
00985 if self._verbose:
00986 self.logh.write("The performance suite results tarball will be stored in CASTOR at %s\n" % self._CASTOR_DIR)
00987 self.logh.write("%s TimeSize events\n" % TimeSizeEvents)
00988 self.logh.write("%s IgProf events\n" % IgProfEvents)
00989 self.logh.write("%s Callgrind events\n" % CallgrindEvents)
00990 self.logh.write("%s Memcheck events\n" % MemcheckEvents)
00991 self.logh.write("%s cmsScimark benchmarks before starting the tests\n" % cmsScimark)
00992 self.logh.write("%s cmsScimarkLarge benchmarks before starting the tests\n" % cmsScimarkLarge)
00993 self.logh.flush()
00994
00995
00996
00997
00998
00999
01000 if len(cpus) > 1:
01001 for cpu in cpus:
01002 cpupath = os.path.join(perfsuitedir,"cpu_%s" % cpu)
01003 if not os.path.exists(cpupath):
01004 os.mkdir(cpupath)
01005
01006 self.Commands = {}
01007 AllScripts = self.Scripts + self.AuxiliaryScripts
01008
01009 for cpu in range(cmsCpuInfo.get_NumOfCores()):
01010 self.Commands[cpu] = []
01011
01012
01013 self.logh.write("Full path of all the scripts used in this run of the Performance Suite:\n")
01014 for script in AllScripts:
01015 which="which " + script
01016
01017
01018
01019
01020 whichstdout=subprocess.Popen(which,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read()
01021 self.logh.write(whichstdout)
01022 if script in self.Scripts:
01023 for cpu in range(cmsCpuInfo.get_NumOfCores()):
01024 command="taskset -c %s %s" % (cpu,script)
01025 self.Commands[cpu].append(command)
01026
01027
01028 scimark = ""
01029 scimarklarge = ""
01030 if not (self._unittest or self._noexec):
01031 for core in range(cores):
01032 if (not core in cpus) and runonspare:
01033 self.logh.write("Submitting cmsScimarkLaunch.csh to run on core cpu "+str(core) + "\n")
01034 subcmd = "cd %s ; cmsScimarkLaunch.csh %s" % (perfsuitedir, str(core))
01035 command="taskset -c %s sh -c \"%s\" &" % (str(core), subcmd)
01036 self.logh.write(command + "\n")
01037
01038
01039
01040
01041
01042 subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
01043
01044 self.logh.flush()
01045
01046
01047 benching = not self._debug
01048
01049
01050 if benching and not (self._unittest or self._noexec):
01051
01052 for cpu in cpus:
01053 scimark = open(os.path.join(perfsuitedir,"cmsScimark2.log") ,"w")
01054 scimarklarge = open(os.path.join(perfsuitedir,"cmsScimark2_large.log"),"w")
01055 if cmsScimark > 0:
01056 self.logh.write("Starting with %s cmsScimark on cpu%s\n" % (cmsScimark,cpu))
01057 cmsScimarkInitialTime=PerfSuiteTimer(start=datetime.datetime.now())
01058 TimerInfo.update({'cmsScimarkTime':{'cmsScimarkInitial':cmsScimarkInitialTime}})
01059 self.benchmarks(cpu,perfsuitedir,scimark.name,cmsScimark)
01060 cmsScimarkInitialTime.set_end(datetime.datetime.now())
01061
01062 if cmsScimarkLarge > 0:
01063 self.logh.write("Following with %s cmsScimarkLarge on cpu%s\n" % (cmsScimarkLarge,cpu))
01064 cmsScimarkLargeInitialTime=PerfSuiteTimer(start=datetime.datetime.now())
01065 TimerInfo['cmsScimarkTime'].update({'cmsScimarkLargeInitial':cmsScimarkLargeInitialTime})
01066 self.benchmarks(cpu,perfsuitedir,scimarklarge.name,cmsScimarkLarge, large=True)
01067 cmsScimarkLargeInitialTime.set_end(datetime.datetime.now())
01068 self.logh.flush()
01069
01070 if (TimeSizePUCandles or IgProfPUCandles or CallgrindPUCandles or MemcheckPUCandles) and not ("FASTSIM" in stepOptions):
01071
01072 PUInputName=os.path.join(perfsuitedir,"INPUT_PILEUP_EVENTS.root")
01073 if PUInputFile:
01074
01075
01076 copycmd="cp"
01077
01078 if '/store/relval/' in PUInputFile:
01079 copycmd="rfcp"
01080
01081
01082 if PUInputFile.startswith('/store/relval/'):
01083 PUInputFile="/castor/cern.ch/cms"+PUInputFile
01084
01085 self.logh.write("Copying the file %s locally to %s\n"%(PUInputFile,PUInputName))
01086 self.logh.flush()
01087 GetPUInput=subprocess.Popen("%s %s %s"%(copycmd,PUInputFile,PUInputName), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
01088 GetPUInputExitCode=GetPUInput.wait()
01089
01090 if GetPUInputExitCode:
01091 self.logh.write("The copying of the pile-up input file returned a non-zero exit code: %s \nThis is the stdout+stderr if the command:\n%s\n"%(GetPUInputExitCode,GetPUInput.stdout))
01092
01093 if not os.path.exists(PUInputName):
01094 self.logh.write("The necessary INPUT_PILEUP_EVENTS.root file was not found in the working directory %s\nExiting now!"%perfsuitedir)
01095 self.logh.flush()
01096 sys.exit(1)
01097 else:
01098
01099 self.printFlush("Some PILE UP tests will be run!")
01100
01101 self.printFlush("cmsdriverPUOptions is %s"%cmsdriverPUOptions)
01102 pass
01103
01104
01105 if TimeSizeEvents > 0:
01106 TimeSizeTime=PerfSuiteTimer(start=datetime.datetime.now())
01107 TimerInfo.update({'TimeSize':{'TotalTime':TimeSizeTime}})
01108 if TimeSizeCandles:
01109 self.logh.write("Launching the TimeSize tests (TimingReport, TimeReport, SimpleMemoryCheck, EdmSize) with %s events each\n" % TimeSizeEvents)
01110 NoPileUpTime=PerfSuiteTimer(start=datetime.datetime.now())
01111 TimerInfo['TimeSize'].update({'NoPileUpTime':NoPileUpTime})
01112 self.printDate()
01113 self.logh.flush()
01114 ReportExit=self.simpleGenReport(cpus,perfsuitedir,TimeSizeEvents,TimeSizeCandles,cmsdriverOptions,stepOptions,"TimeSize",profilers,bypasshlt,userInputFile)
01115 FinalExitCode=FinalExitCode+ReportExit
01116
01117 self.printFlush("Regular TimeSize tests were finished at %s"%(self.getDate()))
01118 NoPileUpTime.set_end(datetime.datetime.now())
01119
01120
01121 if TimeSizePUCandles:
01122 self.logh.write("Launching the PILE UP TimeSize tests (TimingReport, TimeReport, SimpleMemoryCheck, EdmSize) with %s events each\n" % TimeSizeEvents)
01123 PileUpTime=PerfSuiteTimer(start=datetime.datetime.now())
01124 TimerInfo['TimeSize'].update({'PileUpTime':PileUpTime})
01125 self.printDate()
01126 self.logh.flush()
01127 ReportExit=self.simpleGenReport(cpus,perfsuitedir,TimeSizeEvents,TimeSizePUCandles,cmsdriverPUOptions,stepOptions,"TimeSize",profilers,bypasshlt,userInputFile)
01128 FinalExitCode=FinalExitCode+ReportExit
01129
01130 self.printFlush("Pileup TimeSize tests were finished at %s"%(self.getDate()))
01131 PileUpTime.set_end(datetime.datetime.now())
01132
01133
01134 if not (TimeSizeCandles or TimeSizePUCandles):
01135 self.printFlush("A number of events (%s) for TimeSize tests was selected, but no candle for regular or pileup tests was selected!"%(TimeSizeEvents))
01136
01137 self.printFlush("All TimeSize tests were finished at %s"%(self.getDate()))
01138 TimeSizeTime.set_end(datetime.datetime.now())
01139
01140
01141
01142 if not (self._unittest or self._noexec):
01143 self.logh.write("Stopping all cmsScimark jobs now\n")
01144 subcmd = "cd %s ; %s" % (perfsuitedir,self.AuxiliaryScripts[2])
01145 stopcmd = "sh -c \"%s\"" % subcmd
01146 self.printFlush(stopcmd)
01147
01148
01149
01150 self.printFlush(subprocess.Popen(stopcmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read())
01151
01152
01153 if cores==0:
01154
01155 AvailableCores=cpus
01156 else:
01157 AvailableCores=range(cores)
01158
01159 TestsToDo=[]
01160
01161 if IgProfEvents > 0:
01162 if IgProfCandles:
01163 self.printFlush("Preparing IgProf tests")
01164
01165
01166
01167 if profilers:
01168 self.printFlush("Special profiler option for IgProf was indicated by the user: %s"%profilers)
01169
01170 IgProfProfilerArgs={
01171 'perfdir':perfsuitedir,
01172 'NumEvents':IgProfEvents,
01173 'candles':IgProfCandles,
01174 'cmsdriverOptions':cmsdriverOptions,
01175 'stepOptions':stepOptions,
01176 'Name':"IgProf",
01177 'profilers':profilers,
01178 'bypasshlt':bypasshlt,
01179 'userInputRootFiles':userInputFile
01180 }
01181
01182 TestsToDo.append(IgProfProfilerArgs)
01183 self.printFlush("Appended IgProf test with profiler option %s to the TestsToDo list"%profilers)
01184
01185
01186 else:
01187 self.printFlush("Splitting the IgProf tests into Perf and Mem to parallelize the cmsRun execution as much as possible:")
01188
01189
01190 IgProfPerfArgs={
01191 'perfdir':perfsuitedir,
01192 'NumEvents':IgProfEvents,
01193 'candles':IgProfCandles,
01194 'cmsdriverOptions':cmsdriverOptions,
01195 'stepOptions':stepOptions,
01196 'Name':"IgProf_Perf",
01197 'profilers':profilers,
01198 'bypasshlt':bypasshlt,
01199 'userInputRootFiles':userInputFile
01200 }
01201
01202 TestsToDo.append(IgProfPerfArgs)
01203 self.printFlush("Appended IgProf PERF test to the TestsToDo list")
01204
01205
01206 IgProfMemArgs={
01207 'perfdir':perfsuitedir,
01208 'NumEvents':IgProfEvents,
01209 'candles':IgProfCandles,
01210 'cmsdriverOptions':cmsdriverOptions,
01211 'stepOptions':stepOptions,
01212 'Name':"IgProf_Mem",
01213 'profilers':profilers,
01214 'bypasshlt':bypasshlt,
01215 'userInputRootFiles':userInputFile
01216 }
01217
01218 TestsToDo.append(IgProfMemArgs)
01219 self.printFlush("Appended IgProf MEM test to the TestsToDo list")
01220
01221
01222
01223
01224 if IgProfPUCandles:
01225 self.printFlush("Preparing IgProf PileUp tests")
01226
01227
01228
01229 if profilers:
01230 self.printFlush("Special profiler option for IgProf was indicated by the user: %s"%profilers)
01231
01232 IgProfProfilerPUArgs={
01233 'perfdir':perfsuitedir,
01234 'NumEvents':IgProfEvents,
01235 'candles':IgProfPUCandles,
01236 'cmsdriverOptions':cmsdriverPUOptions,
01237 'stepOptions':stepOptions,
01238 'Name':"IgProf",
01239 'profilers':profilers,
01240 'bypasshlt':bypasshlt,
01241 'userInputRootFiles':userInputFile
01242 }
01243
01244 TestsToDo.append(IgProfProfilerPUArgs)
01245 self.printFlush("Appended IgProf PileUp test with profiler option %s to the TestsToDo list"%profilers)
01246 else:
01247 self.printFlush("Splitting the IgProf tests into Perf and Mem to parallelize the cmsRun execution as much as possible:")
01248
01249
01250 IgProfPerfPUArgs={
01251 'perfdir':perfsuitedir,
01252 'NumEvents':IgProfEvents,
01253 'candles':IgProfPUCandles,
01254 'cmsdriverOptions':cmsdriverPUOptions,
01255 'stepOptions':stepOptions,
01256 'Name':"IgProf_Perf",
01257 'profilers':profilers,
01258 'bypasshlt':bypasshlt,
01259 'userInputRootFiles':userInputFile
01260 }
01261
01262 TestsToDo.append(IgProfPerfPUArgs)
01263 self.printFlush("Appended IgProf MEM PileUp test to the TestsToDo list")
01264
01265
01266 IgProfMemPUArgs={
01267 'perfdir':perfsuitedir,
01268 'NumEvents':IgProfEvents,
01269 'candles':IgProfPUCandles,
01270 'cmsdriverOptions':cmsdriverPUOptions,
01271 'stepOptions':stepOptions,
01272 'Name':"IgProf_Mem",
01273 'profilers':profilers,
01274 'bypasshlt':bypasshlt,
01275 'userInputRootFiles':userInputFile
01276 }
01277
01278 TestsToDo.append(IgProfMemPUArgs)
01279 self.printFlush("Appended IgProf MEM PileUp test to the TestsToDo list")
01280 if not (IgProfCandles or IgProfPUCandles):
01281 self.printFlush("A number of events (%s) for IgProf tests was selected, but no candle for regular or pileup tests was selected!"%(IgProfEvents))
01282
01283
01284
01285 if CallgrindEvents > 0:
01286 if CallgrindCandles:
01287 self.printFlush("Preparing Callgrind tests")
01288 CallgrindArgs={
01289 'perfdir':perfsuitedir,
01290 'NumEvents':CallgrindEvents,
01291 'candles':CallgrindCandles,
01292 'cmsdriverOptions':cmsdriverOptions,
01293 'stepOptions':stepOptions,
01294 'Name':"Callgrind",
01295 'profilers':profilers,
01296 'bypasshlt':bypasshlt,
01297 'userInputRootFiles':userInputFile
01298 }
01299
01300 TestsToDo.append(CallgrindArgs)
01301 self.printFlush("Appended Callgrind test to the TestsToDo list")
01302
01303 if CallgrindPUCandles:
01304 self.printFlush("Preparing Callgrind PileUp tests")
01305 CallgrindPUArgs={
01306 'perfdir':perfsuitedir,
01307 'NumEvents':CallgrindEvents,
01308 'candles':CallgrindPUCandles,
01309 'cmsdriverOptions':cmsdriverPUOptions,
01310 'stepOptions':stepOptions,
01311 'Name':"Callgrind",
01312 'profilers':profilers,
01313 'bypasshlt':bypasshlt,
01314 'userInputRootFiles':userInputFile
01315 }
01316
01317 TestsToDo.append(CallgrindPUArgs)
01318 self.printFlush("Appended Callgrind PileUp test to the TestsToDo list")
01319 if not (CallgrindCandles or CallgrindPUCandles):
01320 self.printFlush("A number of events (%s) for Callgrind tests was selected, but no candle for regular or pileup tests was selected!"%(CallgrindEvents))
01321
01322 if MemcheckEvents > 0:
01323 if MemcheckCandles:
01324 self.printFlush("Preparing Memcheck tests")
01325 MemcheckArgs={
01326 'perfdir':perfsuitedir,
01327 'NumEvents':MemcheckEvents,
01328 'candles':MemcheckCandles,
01329 'cmsdriverOptions':cmsdriverOptions,
01330 'stepOptions':stepOptions,
01331 'Name':"Memcheck",
01332 'profilers':profilers,
01333 'bypasshlt':bypasshlt,
01334 'userInputRootFiles':userInputFile
01335 }
01336
01337 TestsToDo.append(MemcheckArgs)
01338 self.printFlush("Appended Memcheck test to the TestsToDo list")
01339
01340 if MemcheckPUCandles:
01341 self.printFlush("Preparing Memcheck PileUp tests")
01342 MemcheckPUArgs={
01343 'perfdir':perfsuitedir,
01344 'NumEvents':MemcheckEvents,
01345 'candles':MemcheckPUCandles,
01346 'cmsdriverOptions':cmsdriverPUOptions,
01347 'stepOptions':stepOptions,
01348 'Name':"Memcheck",
01349 'profilers':profilers,
01350 'bypasshlt':bypasshlt,
01351 'userInputRootFiles':userInputFile
01352 }
01353
01354 TestsToDo.append(MemcheckPUArgs)
01355 self.printFlush("Appended Memcheck PileUp test to the TestsToDo list")
01356 if not (MemcheckCandles or MemcheckPUCandles):
01357 self.printFlush("A number of events (%s) for Memcheck tests was selected, but no candle for regular or pileup tests was selected!"%(MemcheckEvents))
01358
01359
01360
01361 if IgProfEvents or CallgrindEvents or MemcheckEvents:
01362
01363 self.printFlush("Threading all remaining tests on all %s available cores!"%len(AvailableCores))
01364 self.printDate()
01365 self.logh.flush()
01366
01367
01368
01369 OriginalAvailableCores=list(AvailableCores)
01370
01371 self.printFlush("Original available cores list: %s"%AvailableCores)
01372
01373
01374 activePerfTestThreads={}
01375
01376 Waiting=False
01377 while 1:
01378
01379 if TestsToDo:
01380
01381
01382 if not Waiting:
01383 self.printFlush("Currently %s tests are scheduled to be run:"%len(TestsToDo))
01384 self.printFlush(TestsToDo)
01385
01386 if AvailableCores:
01387
01388 Waiting=False
01389 self.printFlush("There is/are %s core(s) available"%len(AvailableCores))
01390 cpu=AvailableCores.pop()
01391 self.printFlush("Let's use cpu %s"%cpu)
01392 simpleGenReportArgs=TestsToDo.pop()
01393 self.printFlush("Let's submit %s test on core %s"%(simpleGenReportArgs['Name'],cpu))
01394
01395 if simpleGenReportArgs['Name'] not in TimerInfo.keys():
01396
01397 self.PerfTestTotalTimer=PerfSuiteTimer(start=datetime.datetime.now())
01398 TimerInfo.update({simpleGenReportArgs['Name']:{'TotalTime':self.PerfTestTotalTimer}})
01399 threadToDo=self.simpleGenReportThread(cpu,self,**simpleGenReportArgs)
01400 self.printFlush("Starting thread %s"%threadToDo)
01401 ReportExitCode=threadToDo.start()
01402 self.printFlush("Adding thread %s to the list of active threads"%threadToDo)
01403 activePerfTestThreads[cpu]=threadToDo
01404
01405 else:
01406 pass
01407
01408 activeTestNames=[]
01409 activeTestNamesPU=[]
01410 for cpu in activePerfTestThreads.keys():
01411 if activePerfTestThreads[cpu].isAlive():
01412
01413 if "--pileup" in activePerfTestThreads[cpu].simpleGenReportArgs['cmsdriverOptions']:
01414 activeTestNamesPU.append(activePerfTestThreads[cpu].simpleGenReportArgs['Name'])
01415 else:
01416 activeTestNames.append(activePerfTestThreads[cpu].simpleGenReportArgs['Name'])
01417 pass
01418 elif cpu not in AvailableCores:
01419
01420 Waiting=False
01421 self.printFlush(time.ctime())
01422 self.printFlush("%s test, in thread %s is done running on core %s"%(activePerfTestThreads[cpu].simpleGenReportArgs['Name'],activePerfTestThreads[cpu],cpu) )
01423 self.printFlush("About to append cpu %s to AvailableCores list"%cpu)
01424 AvailableCores.append(cpu)
01425
01426
01427
01428
01429 if "--pileup" in activePerfTestThreads[cpu].simpleGenReportArgs['cmsdriverOptions']:
01430 try:
01431 activeTestNamesPU.remove(activePerfTestThreads[cpu].simpleGenReportArgs['Name'])
01432 except:
01433 pass
01434 else:
01435 try:
01436 activeTestNames.remove(activePerfTestThreads[cpu].simpleGenReportArgs['Name'])
01437 except:
01438 pass
01439
01440 activePerfTestThreads.pop(cpu)
01441
01442
01443
01444
01445
01446
01447
01448 for TestName in ["IgProf_Perf","IgProf_Mem","Memcheck","Valgrind"]:
01449 if (TestName not in activeTestNames) and (TestName not in activeTestNamesPU) :
01450 try:
01451 TimerInfo[TestName]['TotalTime'].set_end(datetime.datetime.now())
01452 except:
01453
01454 pass
01455
01456
01457
01458 if not AvailableCores==[] and (set(AvailableCores)==set(range(cmsCpuInfo.get_NumOfCores())) or set(AvailableCores)==set(OriginalAvailableCores)) and not TestsToDo:
01459 self.printFlush("PHEW! We're done... all TestsToDo are done... at %s "%(self.getDate()))
01460
01461
01462
01463
01464
01465
01466
01467 break
01468 else:
01469
01470 time.sleep(5)
01471
01472 if not Waiting:
01473 self.printFlush(time.ctime())
01474 self.printFlush("Waiting for tests to be done...")
01475 sys.stdout.flush()
01476 Waiting=True
01477
01478
01479 if benching and not (self._unittest or self._noexec):
01480
01481 for cpu in cpus:
01482 if cmsScimark > 0:
01483 self.logh.write("Ending with %s cmsScimark on cpu%s\n" % (cmsScimark,cpu))
01484 cmsScimarkFinalTime=PerfSuiteTimer(start=datetime.datetime.now())
01485 TimerInfo['cmsScimarkTime'].update({'cmsScimarkFinal':cmsScimarkFinalTime})
01486
01487 self.benchmarks(cpu,perfsuitedir,scimark.name,cmsScimark)
01488 cmsScimarkFinalTime.set_end(datetime.datetime.now())
01489 if cmsScimarkLarge > 0:
01490 self.logh.write("Following with %s cmsScimarkLarge on cpu%s\n" % (cmsScimarkLarge,cpu))
01491 cmsScimarkLargeFinalTime=PerfSuiteTimer(start=datetime.datetime.now())
01492 TimerInfo['cmsScimarkTime'].update({'cmsScimarkLargeFinal':cmsScimarkLargeFinalTime})
01493 self.benchmarks(cpu,perfsuitedir,scimarklarge.name,cmsScimarkLarge,large=True)
01494 cmsScimarkLargeFinalTime.set_end(datetime.datetime.now())
01495
01496 if prevrel:
01497 self.logh.write("Running the regression analysis with respect to %s\n"%getVerFromLog(prevrel))
01498 self.logh.write(time.ctime(time.time()))
01499 self.logh.flush()
01500
01501 crr.regressReports(prevrel,os.path.abspath(perfsuitedir),oldRelName = getVerFromLog(prevrel),newRelName=self.cmssw_version)
01502
01503
01504 if tarball:
01505 tarballTime=PerfSuiteTimer(start=datetime.datetime.now())
01506 TimerInfo.update({'tarballTime':{'TotalTime':tarballTime}})
01507
01508
01509
01510
01511 if "=" in str(stepOptions):
01512 fileStepOption=str(stepOptions).split("=")[1]
01513 else:
01514 fileStepOption=str(stepOptions)
01515 if fileStepOption=="":
01516 fileStepOption="UnknownStep"
01517
01518 fileWorkingDir=os.path.basename(perfsuitedir)
01519
01520
01521
01522
01523 fileEventContentOption="UnknownEventContent"
01524 fileConditionsOption="UnknownConditions"
01525 for token in cmsdriverOptions.split("--"):
01526 if token!='' and 'cmsdriver' not in token:
01527 if "=" in token:
01528 fileOption=token.split("=")[0]
01529 fileOptionValue=token.split("=")[1].strip("'").strip('"')
01530 else:
01531 fileOption=token.split()[0]
01532 fileOptionValue=token.split()[1].strip("'").strip('"')
01533 if "eventcontent" or "conditions" in fileOption:
01534 if "eventcontent" in fileOption:
01535 fileEventContentOption=fileOptionValue
01536 elif "conditions" in fileOption:
01537
01538
01539 if "auto:" in fileOptionValue:
01540 from Configuration.PyReleaseValidation.autoCond import autoCond
01541 fileConditionsOption = autoCond[ fileOptionValue.split(':')[1] ]
01542 else:
01543
01544
01545
01546
01547 if "," in fileOptionValue:
01548 fileConditionsOption=fileOptionValue.split("::")[0].split(",")[1]
01549 else:
01550 fileConditionsOption=fileOptionValue.split("::")[0]
01551 else:
01552
01553 pass
01554
01555
01556
01557
01558
01559
01560
01561
01562 subprocess.Popen("ls -R | grep .root > rootFiles",shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stderr.read()
01563 LogFile = "%s_%s_%s_%s_%s_%s_%s_%s_log.tgz" % (self.cmssw_arch, self.cmssw_version, fileStepOption, fileConditionsOption, fileEventContentOption.split()[0], fileWorkingDir, self.host, self.user)
01564 AbsTarFileLOG = os.path.join(perfsuitedir,LogFile)
01565 tarcmd = "tar zcfX %s %s %s" %(AbsTarFileLOG, "rootFiles", os.path.join(perfsuitedir,"*"))
01566 self.printFlush("Creating a tarball for the logfiles")
01567 self.printFlush(tarcmd)
01568 self.printFlush(subprocess.Popen(tarcmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stderr.read())
01569 self.printFlush(subprocess.Popen("rm rootFiles",shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stderr.read())
01570
01571 fullcastorpathlog=os.path.join(castordir,LogFile)
01572
01573
01574
01575 TarFile = "%s_%s_%s_%s_%s_%s_%s_%s.tgz" % (self.cmssw_arch, self.cmssw_version, fileStepOption, fileConditionsOption, fileEventContentOption.split()[0], fileWorkingDir, self.host, self.user)
01576 AbsTarFile = os.path.join(perfsuitedir,TarFile)
01577 tarcmd = "tar -zcf %s %s" %(AbsTarFile, os.path.join(perfsuitedir,"*"))
01578 md5cmd = "md5sum %s" %(AbsTarFile)
01579 self.printFlush("Creating a tarball with the content of the directory")
01580 self.printFlush(tarcmd)
01581 self.printFlush(md5cmd)
01582
01583
01584
01585
01586
01587 self.printFlush(subprocess.Popen(tarcmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stderr.read())
01588 md5sum = subprocess.Popen(md5cmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read().split()[0]
01589 self.printFlush("The md5 checksum of the tarball: %s" %(md5sum))
01590 AbsTarFileMD5 = AbsTarFile + ".md5"
01591 md5filecmd = "echo %s > %s" % (md5sum, AbsTarFileMD5)
01592 self.printFlush(subprocess.Popen(md5filecmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stderr.read())
01593
01594
01595
01596 fullcastorpathfile=os.path.join(castordir,TarFile)
01597 fullcastorpathmd5=os.path.join(castordir,TarFile + ".md5")
01598
01599 checkcastor="nsls %s" % fullcastorpathfile
01600
01601
01602 checkcastorout=subprocess.Popen(checkcastor,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read()
01603 if checkcastorout.rstrip()==fullcastorpathfile:
01604 castorcmdstderr="File %s is already on CASTOR! Will NOT OVERWRITE!!!"%fullcastorpathfile
01605 else:
01606 castorcmd="rfcp %s %s" % (AbsTarFile,fullcastorpathfile)
01607 castormd5cmd="rfcp %s %s" % (AbsTarFileMD5,fullcastorpathmd5)
01608 castorlogcmd="rfcp %s %s" % (AbsTarFileLOG,fullcastorpathlog)
01609 self.printFlush(castorcmd)
01610 self.printFlush(castormd5cmd)
01611 self.printFlush(castorlogcmd)
01612
01613
01614 castorcmdstderr=subprocess.Popen(castorcmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stderr.read()
01615 subprocess.Popen(castormd5cmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stderr.read()
01616 subprocess.Popen(castorlogcmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stderr.read()
01617
01618 if castorcmdstderr:
01619
01620 self.printFlush(castorcmdstderr)
01621 self.printFlush("Since the CASTOR archiving for the tarball failed the file %s is kept in directory %s"%(TarFile, perfsuitedir))
01622 else:
01623
01624 self.printFlush("Successfully archived the tarball %s in CASTOR!"%(TarFile))
01625 self.printFlush("The tarball can be found: %s"%(fullcastorpathfile))
01626 self.printFlush("The logfile can be found: %s"%(fullcastorpathlog))
01627 self.printFlush("Deleting the local copy of the tarballs")
01628 rmtarballcmd="rm -Rf %s"%(AbsTarFile)
01629 rmtarballmd5cmd="rm -Rf %s"%(AbsTarFileMD5)
01630 rmtarballlogcmd="rm -Rf %s"%(AbsTarFileLOG)
01631 self.printFlush(rmtarballcmd)
01632 self.printFlush(rmtarballmd5cmd)
01633 self.printFlush(rmtarballlogcmd)
01634
01635
01636 self.printFlush(subprocess.Popen(rmtarballcmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.read() )
01637 self.printFlush(subprocess.Popen(rmtarballmd5cmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.read() )
01638 self.printFlush(subprocess.Popen(rmtarballlogcmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.read() )
01639 tarballTime.set_end(datetime.datetime.now())
01640 else:
01641 self.printFlush("Performance Suite directory will not be archived in a tarball since --no_tarball option was chosen")
01642
01643
01644
01645
01646 date=time.ctime(time.time())
01647 self.logh.write("Performance Suite finished running at %s on %s in directory %s\n" % (date,self.host,path))
01648 if self.ERRORS == 0:
01649 self.logh.write("There were no errors detected in any of the log files!\n")
01650 else:
01651 self.logh.write("ERROR: There were %s errors detected in the log files, please revise!\n" % self.ERRORS)
01652
01653
01654 except exceptions.Exception, detail:
01655 self.logh.write(str(detail) + "\n")
01656 self.logh.flush()
01657 if not self.logh.isatty():
01658 self.logh.close()
01659 raise
01660
01661 if MailLogRecipients != "":
01662 self.printFlush("Sending email notification for this execution of the performance suite with command:")
01663 sendLogByMailcmd='cat cmsPerfSuite.log |mail -s "Performance Suite finished running on %s" '%self.host + MailLogRecipients
01664 self.printFlush(sendLogByMailcmd)
01665
01666
01667 self.printFlush(subprocess.Popen(sendLogByMailcmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.read() )
01668 else:
01669 self.printFlush('No email notification will be sent for this execution of the performance suite since option --mail "" was used')
01670
01671 TotalTime.set_end(datetime.datetime.now())
01672 self.printFlush("Total Running Time\t%s hrs (%s mins)"%(TotalTime.get_duration()['hours'],TotalTime.get_duration()['minutes']))
01673
01674
01675
01676
01677 TimerInfoStr={}
01678 PerfSuiteTimerInfo=open("PerfSuiteTimerInfo.pkl","wb")
01679
01680
01681
01682 self.logh.write("Test type\tActual Test\tDuration\tStart Time\tEnd Time\n")
01683 for key in TimerInfo.keys():
01684
01685 TimerInfoStr.update({key:{}})
01686 for test in TimerInfo[key].keys():
01687 TimerInfoStr[key].update({test:[str(TimerInfo[key][test].get_duration()['hours'])+" hrs ("+str(TimerInfo[key][test].get_duration()['minutes'])+" mins)",TimerInfo[key][test].get_start(),TimerInfo[key][test].get_end()]})
01688 self.logh.write(key+"\t"+test+"\t")
01689 self.logh.write("%s hrs (%s mins)\t"%(TimerInfo[key][test].get_duration()['hours'],TimerInfo[key][test].get_duration()['minutes']))
01690 self.logh.write("%s\t"%TimerInfo[key][test].get_start())
01691 self.logh.write("%s\n"%TimerInfo[key][test].get_end())
01692 pickle.dump(TimerInfoStr,PerfSuiteTimerInfo)
01693 PerfSuiteTimerInfo.close()
01694
01695 self.logh.write("Final Performance Suite exit code was %s"%FinalExitCode)
01696 self.logh.flush()
01697 sys.exit(FinalExitCode)
01698
01699 def main(argv=[__name__]):
01700
01701
01702
01703
01704
01705
01706
01707
01708 suite=PerfSuite()
01709
01710
01711
01712
01713
01714 PerfSuiteArgs={}
01715 (PerfSuiteArgs['castordir'],
01716 PerfSuiteArgs['TimeSizeEvents'],
01717 PerfSuiteArgs['IgProfEvents'],
01718 PerfSuiteArgs['CallgrindEvents'],
01719 PerfSuiteArgs['MemcheckEvents'],
01720 PerfSuiteArgs['cmsScimark'],
01721 PerfSuiteArgs['cmsScimarkLarge'],
01722 PerfSuiteArgs['cmsdriverOptions'],
01723 PerfSuiteArgs['cmsdriverPUOptions'],
01724 PerfSuiteArgs['stepOptions'],
01725 PerfSuiteArgs['quicktest'],
01726 PerfSuiteArgs['profilers'],
01727 PerfSuiteArgs['cpus'],
01728 PerfSuiteArgs['cores'],
01729 PerfSuiteArgs['prevrel'],
01730 PerfSuiteArgs['bypasshlt'],
01731 PerfSuiteArgs['runonspare'],
01732 PerfSuiteArgs['perfsuitedir'],
01733 PerfSuiteArgs['logfile'],
01734 PerfSuiteArgs['TimeSizeCandles'],
01735 PerfSuiteArgs['IgProfCandles'],
01736 PerfSuiteArgs['CallgrindCandles'],
01737 PerfSuiteArgs['MemcheckCandles'],
01738 PerfSuiteArgs['TimeSizePUCandles'],
01739 PerfSuiteArgs['IgProfPUCandles'],
01740 PerfSuiteArgs['CallgrindPUCandles'],
01741 PerfSuiteArgs['MemcheckPUCandles'],
01742 PerfSuiteArgs['PUInputFile'],
01743 PerfSuiteArgs['userInputFile'],
01744 PerfSuiteArgs['MailLogRecipients'],
01745 PerfSuiteArgs['tarball']
01746 ) = suite.optionParse(argv)
01747
01748 if not PerfSuiteArgs['logfile'] == None:
01749 if os.path.exists(PerfSuiteArgs['logfile']):
01750 oldlogfile=PerfSuiteArgs['logfile']+"_"+time.strftime("%d-%m-%Y_%H:%M:%S")
01751
01752 mvOldLogfile=subprocess.Popen("mv %s %s"%(PerfSuiteArgs['logfile'],oldlogfile), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
01753 mvOldLogfileExitCode=mvOldLogfile.wait()
01754
01755 try:
01756 ActualLogfile = open(PerfSuiteArgs['logfile'],"w")
01757 if mvOldLogfileExitCode:
01758 ActualLogfile.write("Please check what happened: A file named %s existed already and the attempt to move it to %s produced the following output: %s\n"%(PerfSuiteArgs['logfile'],oldlogfile,mvOldLogfile.stdout))
01759 else:
01760 ActualLogfile.write("***WARNING! A file named %s existed already!\n***It has been moved to %s before starting the current logfile!\n"%(PerfSuiteArgs['logfile'],oldlogfile))
01761 except (OSError, IOError), detail:
01762 ActualLogfile.write("Failed to open the intended logfile %s, detail error:\n%s"%(PerfSuiteArgs['logfile'],detail))
01763
01764 else:
01765 try:
01766 ActualLogfile = open(PerfSuiteArgs['logfile'],"w")
01767 except (OSError, IOError), detail:
01768 ActualLogfile.write("Failed to open the intended logfile %s, detail error:\n%s"%(PerfSuiteArgs['logfile'],detail))
01769 ActualLogfile.flush()
01770
01771
01772 ActualLogfile.write("Performance suite invoked with command line:\n")
01773 cmdline=reduce(lambda x,y:x+" "+y,sys.argv)
01774 ActualLogfile.write(cmdline+"\n")
01775 ActualLogfile.flush()
01776
01777
01778 ActualLogfile.write("Initial PerfSuite Arguments:\n")
01779 for key in PerfSuiteArgs.keys():
01780 ActualLogfile.write("%s %s\n"%(key,PerfSuiteArgs[key]))
01781 ActualLogfile.flush()
01782
01783
01784
01785 if len(PerfSuiteArgs['cpus']) > 1:
01786 ActualLogfile.write("More than 1 cpu: threading the Performance Suite!\n")
01787 outputdir=PerfSuiteArgs['perfsuitedir']
01788 runonspare=PerfSuiteArgs['runonspare']
01789 cpus=PerfSuiteArgs['cpus']
01790 if runonspare:
01791 for core in range(PerfSuiteArgs['cores']):
01792 cmsScimarkLaunch_pslist={}
01793 if (core not in cpus):
01794
01795 ActualLogfile.write("Submitting cmsScimarkLaunch.csh to run on core cpu "+str(core)+"\n")
01796 subcmd = "cd %s ; cmsScimarkLaunch.csh %s" % (outputdir, str(core))
01797 command="taskset -c %s sh -c \"%s\" &" % (str(core), subcmd)
01798
01799 ActualLogfile.write(command+"\n")
01800
01801
01802 cmsScimarkLaunch_pslist[core]=subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
01803 ActualLogfile.write("Spawned %s \n with PID %s"%(command,cmsScimarkLaunch_pslist[core].pid))
01804 ActualLogfile.flush()
01805 PerfSuiteArgs['runonspare']=False
01806 logfile=PerfSuiteArgs['logfile']
01807 suitethread={}
01808 for cpu in cpus:
01809
01810
01811
01812
01813
01814 cpudir = os.path.join(outputdir,"cpu_%s" % cpu)
01815 if not os.path.exists(cpudir):
01816 os.mkdir(cpudir)
01817 PerfSuiteArgs['perfsuitedir']=cpudir
01818 PerfSuiteArgs['cpus']=[cpu]
01819 if PerfSuiteArgs['logfile']:
01820 PerfSuiteArgs['logfile']=os.path.join(cpudir,os.path.basename(PerfSuiteArgs['logfile']))
01821 else:
01822 PerfSuiteArgs['logfile']=os.path.join(cpudir,"cmsPerfSuiteThread.log")
01823
01824 suitethread[cpu]=PerfThread(**PerfSuiteArgs)
01825 ActualLogfile.write(suitethread[cpu])
01826 ActualLogfile.write("Launching PerfSuite thread on cpu%s"%cpu)
01827 ActualLogfile.flush()
01828
01829
01830 suitethread[cpu].start()
01831
01832 while reduce(lambda x,y: x or y, map(lambda x: x.isAlive(),suitethread.values())):
01833 try:
01834 time.sleep(5.0)
01835 sys.stdout.flush()
01836 except (KeyboardInterrupt, SystemExit):
01837 raise
01838 ActualLogfile.write("All PerfSuite threads have completed!\n")
01839 ActualLogfile.flush()
01840
01841 else:
01842 suite.runPerfSuite(**PerfSuiteArgs)
01843
01844 if __name__ == "__main__":
01845
01846 main(sys.argv)