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