Public Member Functions | |
def | __init__ |
def | make_profile |
def | make_report |
Public Attributes | |
command | |
profile_name | |
profiler | |
Private Member Functions | |
def | _profile_edmsize |
def | _profile_igprof |
def | _profile_Memcheck_Valgrind |
def | _profile_None |
def | _profile_SimpleMem_Parser |
def | _profile_Timereport_Parser |
def | _profile_Timing_Parser |
def | _profile_valgrindfce |
def | _save_output |
Class that represents the procedure of performance report creation
Definition at line 268 of file cmsRelvalreport.py.
def cmsRelvalreport::Profile::__init__ | ( | self, | |
command, | |||
profiler, | |||
profile_name | |||
) |
Definition at line 272 of file cmsRelvalreport.py.
def cmsRelvalreport::Profile::_profile_edmsize | ( | self | ) | [private] |
Launch edm size profiler
Definition at line 355 of file cmsRelvalreport.py.
00356 : 00357 ''' 00358 Launch edm size profiler 00359 ''' 00360 # In this case we replace the name to be clear 00361 input_rootfile=self.command 00362 00363 # Skim the content if requested! 00364 if '.' in self.profiler: 00365 00366 clean_profiler_name,options=self.profiler.split('.') 00367 content,nevts=options.split(',') 00368 outfilename='%s_%s.root'%(os.path.basename(self.command)[:-6],content) 00369 oldpypath=os.environ['PYTHONPATH'] 00370 os.environ['PYTHONPATH']+=':%s' %MAKESKIMDRIVERDIR 00371 execute('%s -i %s -o %s --outputcommands %s -n %s' %(MAKESKIMDRIVER, 00372 self.command, 00373 outfilename, 00374 content, 00375 nevts)) 00376 os.environ['PYTHONPATH']=oldpypath 00377 #execute('rm %s' %outfilename) 00378 self.command=outfilename 00379 self.profiler=clean_profiler_name 00380 00381 00382 profiler_line='edmEventSize -o %s -d %s'\ 00383 %(self.profile_name,self.command) 00384 00385 return execute(profiler_line)
def cmsRelvalreport::Profile::_profile_igprof | ( | self | ) | [private] |
IgProf profiler launcher.
Definition at line 327 of file cmsRelvalreport.py.
00327 : 00328 ''' 00329 IgProf profiler launcher. 00330 ''' 00331 profiler_line='' 00332 00333 igprof_options='igprof -d -t %s ' \ 00334 %EXECUTABLE # IgProf profile not general only for CMSRUN! 00335 00336 # To handle Igprof memory and performance profiler in one function 00337 if self.profiler=='IgProf_perf': 00338 igprof_options+='-pp ' 00339 elif self.profiler=='IgProf_mem': 00340 igprof_options+='-mp ' 00341 else: 00342 raise ('Unknown IgProf flavour: %s !'%self.profiler) 00343 igprof_options+='-z -o %s' %(self.profile_name) 00344 00345 # If we are using cmsDriver we should use the prefix switch 00346 if EXECUTABLE=='cmsRun' and self.command.find('cmsDriver.py')!=-1: 00347 profiler_line='%s --prefix "%s"' %(self.command,igprof_options) 00348 else: 00349 profiler_line='%s %s' %(igprof_options, self.command) 00350 00351 return execute(profiler_line) 00352
def cmsRelvalreport::Profile::_profile_Memcheck_Valgrind | ( | self | ) | [private] |
Valgrind Memcheck profile launcher
Definition at line 388 of file cmsRelvalreport.py.
00389 : 00390 ''' 00391 Valgrind Memcheck profile launcher 00392 ''' 00393 profiler_line='' 00394 #Adding cms suppression of useless messages (cmsvgsupp) 00395 #Removing leak-checking (done with igprof) 00396 #'--leak-check=no '+\ (no is the default) 00397 #'--show-reachable=yes '+\ 00398 #'--track-fds=yes ' 00399 #Adding xml logging 00400 valgrind_options='time valgrind --tool=memcheck `cmsvgsupp` '+\ 00401 '--num-callers=20 '+\ 00402 '--xml=yes '+\ 00403 '--xml-file=%s.xml '%self.profile_name.replace(",","-")[:-4] 00404 00405 # If we are using cmsDriver we should use the prefix switch 00406 if EXECUTABLE=='cmsRun' and self.command.find('cmsDriver.py')!=-1: 00407 #Replacing 2>&1 |tee with >& in the shell command to preserve the return code significance: 00408 # using tee return would be 0 even if the command failed before the pipe: 00409 profiler_line='%s --prefix "%s" >& %s' %(self.command,valgrind_options,self.profile_name) 00410 00411 else: 00412 profiler_line='%s %s >& %s' %(valgrind_options,self.command,self.profile_name) 00413 #'--trace-children=yes '+\ return execute(profiler_line)
def cmsRelvalreport::Profile::_profile_None | ( | self | ) | [private] |
Just Run the command!
Definition at line 445 of file cmsRelvalreport.py.
def cmsRelvalreport::Profile::_profile_SimpleMem_Parser | ( | self | ) | [private] |
Definition at line 421 of file cmsRelvalreport.py.
def cmsRelvalreport::Profile::_profile_Timereport_Parser | ( | self | ) | [private] |
Definition at line 416 of file cmsRelvalreport.py.
def cmsRelvalreport::Profile::_profile_Timing_Parser | ( | self | ) | [private] |
Definition at line 426 of file cmsRelvalreport.py.
def cmsRelvalreport::Profile::_profile_valgrindfce | ( | self | ) | [private] |
Valgrind profile launcher.
Definition at line 304 of file cmsRelvalreport.py.
00305 : 00306 ''' 00307 Valgrind profile launcher. 00308 ''' 00309 # ValgrindFCE needs a special library to run 00310 os.environ["VALGRIND_LIB"]=VFCE_LIB 00311 00312 profiler_line='' 00313 valgrind_options= 'time valgrind '+\ 00314 '--tool=callgrind '+\ 00315 '--fce=%s ' %(self.profile_name) 00316 00317 # If we are using cmsDriver we should use the prefix switch 00318 if EXECUTABLE=='cmsRun' and self.command.find('cmsDriver.py')!=-1: 00319 profiler_line='%s --prefix "%s"' %(self.command,valgrind_options) 00320 00321 else: 00322 profiler_line='%s %s' %(valgrind_options,self.command) 00323 #'--trace-children=yes '+\ 00324 00325 return execute(profiler_line)
def cmsRelvalreport::Profile::_save_output | ( | self | ) | [private] |
Save the output of cmsRun on a file!
Definition at line 431 of file cmsRelvalreport.py.
00432 : 00433 ''' 00434 Save the output of cmsRun on a file! 00435 ''' 00436 # # a first maquillage about the profilename: 00437 # if self.profile_name[-4:]!='.log': 00438 # self.profile_name+='.log' 00439 #Replacing 2>&1 |tee with >& in the shell command to preserve the return code significance: 00440 # using tee return would be 0 even if the command failed before the pipe: 00441 profiler_line='%s >& %s' %(self.command,self.profile_name) 00442 return execute(profiler_line)
def cmsRelvalreport::Profile::make_profile | ( | self | ) |
Launch the right function according to the profiler name.
Definition at line 279 of file cmsRelvalreport.py.
00280 : 00281 ''' 00282 Launch the right function according to the profiler name. 00283 ''' 00284 if self.profiler=='ValgrindFCE': 00285 return self._profile_valgrindfce() 00286 elif self.profiler.find('IgProf')!=-1: 00287 return self._profile_igprof() 00288 elif self.profiler.find('Edm_Size')!=-1: 00289 return self._profile_edmsize() 00290 elif self.profiler=='Memcheck_Valgrind': 00291 return self._profile_Memcheck_Valgrind() 00292 elif self.profiler=='Timereport_Parser': 00293 return self._profile_Timereport_Parser() 00294 elif self.profiler=='Timing_Parser': 00295 return self._profile_Timing_Parser() 00296 elif self.profiler=='SimpleMem_Parser': 00297 return self._profile_SimpleMem_Parser() 00298 elif self.profiler=='': 00299 return self._profile_None() 00300 elif self.profiler=='None': #adding this for the case of candle ASCII file non-profiling commands 00301 return self._profile_None() 00302 else: raise('No %s profiler found!' %self.profiler)
def cmsRelvalreport::Profile::make_report | ( | self, | |
fill_db = False , |
|||
db_name = None , |
|||
tmp_dir = None , |
|||
outdir = None , |
|||
IgProf_option = None , |
|||
metastring = None |
|||
) |
Make a performance report with CMSSW scripts for CMSSW internal profiling (Timing/SimpleMemoryCheck) and Memcheck, PR2 for edmEventSize and Callgrind (NOTE PR2 is not supported anymore and is not currently in the CMSSW external, running froma privat AFS!), igprof-analyse for all IgProf profiling.
Definition at line 453 of file cmsRelvalreport.py.
00460 : 00461 ''' 00462 Make a performance report with CMSSW scripts for CMSSW internal profiling (Timing/SimpleMemoryCheck) and Memcheck, PR2 for edmEventSize and Callgrind (NOTE PR2 is not supported anymore and is not currently in the CMSSW external, running froma privat AFS!), igprof-analyse for all IgProf profiling. 00463 ''' 00464 00465 if outdir==None or outdir==self.profile_name: 00466 outdir=self.profile_name+'_outdir' 00467 00468 #Create the directory where the report will be stored: 00469 if not os.path.exists(outdir) and not fill_db and not IgProf_option: 00470 #Added an IgProf condition to avoid the creation of a directory that we will not need anymore, since we will put all info in the filenames 00471 execute('mkdir %s' %outdir) 00472 00473 if fill_db: 00474 db_option='-a' 00475 if not os.path.exists(db_name): 00476 db_option='-A' 00477 00478 # temp in the local dir for PR 00479 tmp_switch='' 00480 if tmp_dir!='': 00481 execute('mkdir %s' %tmp_dir) 00482 tmp_switch=' -t %s' %tmp_dir 00483 00484 #Handle the various profilers: 00485 00486 ##################################################################### 00487 00488 # Profiler is ValgrindFCE: 00489 if self.profiler=='ValgrindFCE': 00490 perfreport_command='' 00491 # Switch for filling the db 00492 if not fill_db: 00493 os.environ["PERFREPORT_PATH"]='%s/' %PERFREPORT2_PATH 00494 perfreport_command='%s %s -ff -i %s -o %s' %(PR2, 00495 tmp_switch, 00496 self.profile_name, 00497 outdir) 00498 else: 00499 os.environ["PERFREPORT_PATH"]='%s/' %PERFREPORT3_PATH 00500 perfreport_command='%s %s -n5000 -u%s -ff -m \'scram_cmssw_version_string,%s\' -i %s %s -o %s' \ 00501 %(PR3, 00502 tmp_switch, 00503 PR3_PRODUCER_PLUGIN, 00504 metastring, 00505 self.profile_name, 00506 db_option, 00507 db_name) 00508 return execute(perfreport_command) 00509 00510 ##################################################################### 00511 00512 # Profiler is IgProf: 00513 if self.profiler.find('IgProf')!=-1: 00514 #First the case of IgProf PERF and MEM reporting: 00515 if not 'ANALYSE' in IgProf_option: 00516 #Switch to the use of igprof-analyse instead of PerfReport! 00517 #Will use the ANALYSE case for regressions between early event dumps and late event dumps of the profiles 00518 #Following Andreas suggestion, add the number of events for the EndOfJob report 00519 NumberOfEvents=self.command.split()[3] #FIXME: this is quite hardcoded... but should be stable... 00520 sqlite_outputfile=self.profile_name.split(".")[0].replace(IgProfProfiles[IgProf_option[0]],IgProf_option[0])+'___'+NumberOfEvents+'_EndOfJob.sql3' 00521 logger("Executing the report of the IgProf end of job profile") 00522 exit=execute('igprof-analyse --sqlite -d -v -g -r %s %s | sqlite3 %s'%(IgProf_option[0],self.profile_name,sqlite_outputfile)) 00523 return exit 00524 #Then the "ANALYSE" case that we want to use to add to the same directories (Perf, MemTotal, MemLive) 00525 #also some other analyses and in particular: 00526 #1-the first 7 lines of the ASCII analysis of the IgProf profile dumps (total of the counters) 00527 #2-the dump at different event numbers, 00528 #3-the diff between the first and last dump, 00529 #4-the counters grouped by library using regexp at the last dump: 00530 else: #We use IgProf Analysis 00531 #Set the IgProfCounter from the ANALYSE.MEM_TOT style IgProf_option 00532 #print IgProf_option 00533 IgProfCounter=IgProf_option[1] 00534 #Add here the handling of the new IgProf.N.gz files so that they will get preserved and not overwritten: 00535 logger("Looking for IgProf intermediate event profile dumps") 00536 #Check if there are IgProf.N.gz dump files: 00537 IgProfDumps=glob.glob("IgProf.*.gz") 00538 #in case there are none check if they have already been mv'd to another name to avoid overwriting 00539 #(MEM_LIVE usually re-uses MEM_TOTAL, so the IgProf.N.gz files will already have a MemTotal name...) 00540 if not IgProfDumps: 00541 localFiles=os.listdir('.') 00542 IgProfDumpProfilesPrevious=re.compile(r"\w+.\d+.gz") 00543 IgProfDumps=filter(lambda x: IgProfDumpProfilesPrevious.search(x),localFiles) 00544 #Now if there are dumps execute the following analyses: 00545 if IgProfDumps: 00546 IgProfDumps.sort() 00547 logger("Found the following IgProf intermediate event profile dumps:") 00548 logger(IgProfDumps) 00549 FirstDumpEvent=9999999 00550 LastDumpEvent=0 00551 exit=0 00552 for dump in IgProfDumps: 00553 if "___" in dump: 00554 DumpEvent=dump.split(".")[0].split("___")[-1] 00555 else: 00556 DumpEvent=dump.split(".")[1] 00557 #New naming convention using ___ as separator 00558 DumpedProfileName=self.profile_name[:-3]+"___"+DumpEvent+".gz" 00559 if dump.startswith("IgProf"): 00560 execute('mv %s %s'%(dump,DumpedProfileName)) 00561 #Keep a tab of the first and last dump event for the diff analysis 00562 if int(DumpEvent) < FirstDumpEvent: 00563 FirstDumpEvent = int(DumpEvent) 00564 if int(DumpEvent) > LastDumpEvent: 00565 LastDumpEvent = int(DumpEvent) 00566 #Eliminating the ASCII analysis to get the totals, Giulio will provide this information in igprof-navigator with a special query 00567 #First type of analysis: dump first 7 lines of ASCII analysis: 00568 #logger("Executing the igprof-analyse analysis to dump the ASCII 7 lines output with the totals for the IgProf counter") 00569 #exit=execute('%s -o%s -i%s -t%s' %(IGPROFANALYS,outdir,DumpedProfileName,"ASCII")) 00570 #Second type of analysis: dump the report in sqlite format to be ready to be browsed with igprof-navigator 00571 logger("Executing the igprof-analyse analysis saving into igprof-navigator browseable SQLite3 format") 00572 #exit=exit+execute('%s -o%s -i%s -t%s' %(IGPROFANALYS,outdir,DumpedProfileName,"SQLite3")) 00573 #Execute all types of analyses available with the current profile (using the dictionary IgProfProfile): 00574 #To avoid this we should use a further input in SimulationCandles.txt IgProfMem.ANALYSE.MEM_TOTAL maybe the cleanest solution. 00575 #for IgProfile in IgProfCounters.keys(): 00576 # if DumpedProfileName.find(IgProfile)>0: 00577 # for counter in IgProfCounters[IgProfile]: 00578 #Check that the file does not exist: 00579 #if not os.path.exists(DumpedProfileName.split(".")[0].replace(IgProfProfiles[counter],counter)+".sql3"): 00580 exit=exit+execute('%s -c%s -i%s -t%s' %(IGPROFANALYS,IgProfCounter,DumpedProfileName,"SQLite3")) 00581 #else: 00582 # print "File %s already exists will not process profile"%DumpedProfileName.split(".")[0].replace(IgProfProfiles[counter],counter)+".sql3" 00583 #FIXME: 00584 #Issue with multiple profiles in the same dir: assuming Perf and Mem will always be in separate dirs 00585 #Potential ssue with multiple steps? 00586 #Adapting to new igprof naming scheme: 00587 FirstDumpProfile=self.profile_name[:-3]+"___"+str(FirstDumpEvent)+".gz" 00588 LastDumpProfile=self.profile_name[:-3]+"___"+str(LastDumpEvent)+".gz" 00589 #Third type of analysis: execute the diff analysis: 00590 #Check there are at least 2 IgProf intermediate event dump profiles to do a regression! 00591 if len(IgProfDumps)>1: 00592 logger("Executing the igprof-analyse regression between the first IgProf profile dump and the last one") 00593 #for IgProfile in IgProfCounters.keys(): 00594 # if DumpedProfileName.find(IgProfile)>0: 00595 # IgProfCounter=IgProfCounters[IgProfile] 00596 exit=exit+execute('%s -c%s -i%s -r%s' %(IGPROFANALYS,IgProfCounter,LastDumpProfile,FirstDumpProfile)) 00597 else: 00598 logger("CANNOT execute any regressions: not enough IgProf intermediate event profile dumps!") 00599 #Fourth type of analysis: execute the grouped by library igprof-analyse: 00600 logger("Executing the igprof-analyse analysis merging the results by library via regexp and saving the result in igprof-navigator browseable SQLite3 format") 00601 #for IgProfile in IgProfCounters.keys(): 00602 # if DumpedProfileName.find(IgProfile)>0: 00603 # IgProfCounter=IgProfCounters[IgProfile] 00604 exit=exit+execute('%s -c%s -i%s --library' %(IGPROFANALYS,IgProfCounter,LastDumpProfile)) 00605 #If they are not there at all (no dumps) 00606 else: 00607 logger("No IgProf intermediate event profile dumps found!") 00608 exit=0 00609 00610 return exit 00611 00612 00613 ##################################################################### 00614 00615 # Profiler is EdmSize: 00616 if 'Edm_Size' in self.profiler: 00617 perfreport_command='' 00618 if not fill_db: 00619 os.environ["PERFREPORT_PATH"]='%s/' \ 00620 %PERFREPORT2_PATH 00621 perfreport_command='%s %s -fe -i %s -o %s' \ 00622 %(PR2, 00623 tmp_switch, 00624 self.profile_name, 00625 outdir) 00626 else: 00627 os.environ["PERFREPORT_PATH"]='%s/' \ 00628 %PERFREPORT3_PATH 00629 perfreport_command='%s %s -n5000 -u%s -fe -i %s -a -o %s' \ 00630 %(PR3, 00631 tmp_switch, 00632 PR3_PRODUCER_PLUGIN, 00633 self.profile_name, 00634 db_name) 00635 00636 return execute(perfreport_command) 00637 00638 #FIXME: probably need to move this somewhere else now that we use return statements 00639 if tmp_dir!='': 00640 execute('rm -r %s' %tmp_dir) 00641 00642 ##################################################################### 00643 00644 # Profiler is Valgrind Memcheck 00645 if self.profiler=='Memcheck_Valgrind': 00646 # Three pages will be produced: 00647 os.environ['PERL5LIB']=PERL5_LIB 00648 report_coordinates=(VMPARSER,self.profile_name,outdir) 00649 # Copy the Valgrind Memcheck parser style file in the outdir 00650 copyStyleFile='cp -pR %s %s'%(VMPARSERSTYLE,outdir) 00651 execute(copyStyleFile) 00652 report_commands=('%s --preset +prod,-prod1 %s > %s/edproduce.html'\ 00653 %report_coordinates, 00654 '%s --preset +prod1 %s > %s/esproduce.html'\ 00655 %report_coordinates, 00656 '%s -t beginJob %s > %s/beginjob.html'\ 00657 %report_coordinates) 00658 exit=0 00659 for command in report_commands: 00660 exit= exit + execute(command) 00661 return exit 00662 ##################################################################### 00663 00664 # Profiler is TimeReport parser 00665 00666 if self.profiler=='Timereport_Parser': 00667 return execute('%s %s %s' %(TIMEREPORTPARSER,self.profile_name,outdir)) 00668 00669 ##################################################################### 00670 00671 # Profiler is Timing Parser 00672 00673 if self.profiler=='Timing_Parser': 00674 return execute('%s -i %s -o %s' %(TIMINGPARSER,self.profile_name,outdir)) 00675 00676 00677 ##################################################################### 00678 00679 # Profiler is Simple memory parser 00680 00681 if self.profiler=='SimpleMem_Parser': 00682 return execute('%s -i %s -o %s' %(SIMPLEMEMPARSER,self.profile_name,outdir)) 00683 00684 ##################################################################### 00685 00686 # no profiler 00687 00688 if self.profiler=='' or self.profiler=='None': #Need to catch the None case, since otherwise we get no return code (crash for pre-requisite step running). 00689 return 0 #Used to be pass, but we need a return 0 to handle exit code properly!
Definition at line 272 of file cmsRelvalreport.py.
Definition at line 272 of file cmsRelvalreport.py.
Definition at line 272 of file cmsRelvalreport.py.