CMS 3D CMS Logo

Public Member Functions | Public Attributes | Private Member Functions

cmsRelvalreport::Profile Class Reference

List of all members.

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

Detailed Description

Class that represents the procedure of performance report creation

Definition at line 268 of file cmsRelvalreport.py.


Constructor & Destructor Documentation

def cmsRelvalreport::Profile::__init__ (   self,
  command,
  profiler,
  profile_name 
)

Definition at line 272 of file cmsRelvalreport.py.

00273                                                     :
00274         self.command=command
00275         self.profile_name=profile_name
00276         self.profiler=profiler
    

Member Function Documentation

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.

00446                            :
00447         '''
00448         Just Run the command!
00449         '''
00450         return execute(self.command)
    
def cmsRelvalreport::Profile::_profile_SimpleMem_Parser (   self) [private]

Definition at line 421 of file cmsRelvalreport.py.

00422                                        :
00423         return self._save_output()

def cmsRelvalreport::Profile::_profile_Timereport_Parser (   self) [private]

Definition at line 416 of file cmsRelvalreport.py.

00417                                         :
00418         return self._save_output()
        
def cmsRelvalreport::Profile::_profile_Timing_Parser (   self) [private]

Definition at line 426 of file cmsRelvalreport.py.

00427                                     :
00428         return self._save_output()     
    
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!         
                                                                

Member Data Documentation

Definition at line 272 of file cmsRelvalreport.py.

Definition at line 272 of file cmsRelvalreport.py.

Definition at line 272 of file cmsRelvalreport.py.