CMS 3D CMS Logo

List of all members | Public Member Functions | Public Attributes | Private Member Functions
cmsRelvalreport.Profile Class Reference

Public Member Functions

def __init__ (self, command, profiler, profile_name)
 
def make_profile (self)
 
def make_report (self, fill_db=False, db_name=None, tmp_dir=None, outdir=None, IgProf_option=None, metastring=None)
 

Public Attributes

 command
 
 profile_name
 
 profiler
 

Private Member Functions

def _profile_edmsize (self)
 
def _profile_igprof (self)
 
def _profile_Memcheck_Valgrind (self)
 
def _profile_None (self)
 
def _profile_SimpleMem_Parser (self)
 
def _profile_Timereport_Parser (self)
 
def _profile_Timing_Parser (self)
 
def _profile_valgrindfce (self)
 
def _save_output (self)
 

Detailed Description

Class that represents the procedure of performance report creation

Definition at line 269 of file cmsRelvalreport.py.

Constructor & Destructor Documentation

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

Definition at line 273 of file cmsRelvalreport.py.

273  def __init__(self,command,profiler,profile_name):
274  self.command=command
275  self.profile_name=profile_name
276  self.profiler=profiler
277 
def __init__(self, command, profiler, profile_name)

Member Function Documentation

def cmsRelvalreport.Profile._profile_edmsize (   self)
private
Launch edm size profiler

Definition at line 356 of file cmsRelvalreport.py.

References runall.testit.command, cmsswPreprocessor.CmsswPreprocessor.command, WorkFlow.WorkFlowBlock.command, cmsRelvalreport.Profile.command, cmsRelvalreport.execute(), cmsRelvalreport.Profile.profile_name, and cmsRelvalreport.Profile.profiler.

Referenced by cmsRelvalreport.Profile.make_profile().

356  def _profile_edmsize(self):
357  '''
358  Launch edm size profiler
359  '''
360  # In this case we replace the name to be clear
361  input_rootfile=self.command
362 
363  # Skim the content if requested!
364  if '.' in self.profiler:
365 
366  clean_profiler_name,options=self.profiler.split('.')
367  content,nevts=options.split(',')
368  outfilename='%s_%s.root'%(os.path.basename(self.command)[:-6],content)
369  oldpypath=os.environ['PYTHONPATH']
370  os.environ['PYTHONPATH']+=':%s' %MAKESKIMDRIVERDIR
371  execute('%s -i %s -o %s --outputcommands %s -n %s' %(MAKESKIMDRIVER,
372  self.command,
373  outfilename,
374  content,
375  nevts))
376  os.environ['PYTHONPATH']=oldpypath
377  #execute('rm %s' %outfilename)
378  self.command=outfilename
379  self.profiler=clean_profiler_name
380 
381 
382  profiler_line='edmEventSize -o %s -d %s'\
383  %(self.profile_name,self.command)
384 
385  return execute(profiler_line)
386 
def execute(command)
def cmsRelvalreport.Profile._profile_igprof (   self)
private
IgProf profiler launcher.

Definition at line 328 of file cmsRelvalreport.py.

References runall.testit.command, cmsswPreprocessor.CmsswPreprocessor.command, WorkFlow.WorkFlowBlock.command, cmsRelvalreport.Profile.command, cmsRelvalreport.execute(), cmsRelvalreport.Profile.profile_name, and cmsRelvalreport.Profile.profiler.

Referenced by cmsRelvalreport.Profile.make_profile().

328  def _profile_igprof(self):
329  '''
330  IgProf profiler launcher.
331  '''
332  profiler_line=''
333 
334  igprof_options='igprof -d -t %s ' \
335  %EXECUTABLE # IgProf profile not general only for CMSRUN!
336 
337  # To handle Igprof memory and performance profiler in one function
338  if self.profiler=='IgProf_perf':
339  igprof_options+='-pp '
340  elif self.profiler=='IgProf_mem':
341  igprof_options+='-mp '
342  else:
343  raise 'Unknown IgProf flavour: %s !'
344  igprof_options+='-z -o %s' %(self.profile_name)
345 
346  # If we are using cmsDriver we should use the prefix switch
347  if EXECUTABLE=='cmsRun' and self.command.find('cmsDriver.py')!=-1:
348  profiler_line='%s --prefix "%s"' %(self.command,igprof_options)
349  else:
350  profiler_line='%s %s' %(igprof_options, self.command)
351 
352  return execute(profiler_line)
353 
def execute(command)
def cmsRelvalreport.Profile._profile_Memcheck_Valgrind (   self)
private
Valgrind Memcheck profile launcher

Definition at line 389 of file cmsRelvalreport.py.

References runall.testit.command, cmsswPreprocessor.CmsswPreprocessor.command, WorkFlow.WorkFlowBlock.command, cmsRelvalreport.Profile.command, cmsRelvalreport.execute(), and cmsRelvalreport.Profile.profile_name.

Referenced by cmsRelvalreport.Profile.make_profile().

390  '''
391  Valgrind Memcheck profile launcher
392  '''
393  profiler_line=''
394  #Adding cms suppression of useless messages (cmsvgsupp)
395  #Removing leak-checking (done with igprof)
396  #'--leak-check=no '+\ (no is the default)
397  #'--show-reachable=yes '+\
398  #'--track-fds=yes '
399  #Adding xml logging
400  xmlFileName = self.profile_name.replace(",","-")[:-4] + ".xml"
401  valgrind_options='time valgrind --track-origins=yes '+\
402  '--tool=memcheck `cmsvgsupp` '+\
403  '--num-callers=20 '+\
404  '--xml=yes '+\
405  '--xml-file=%s '%xmlFileName
406 
407  # If we are using cmsDriver we should use the prefix switch
408  if EXECUTABLE=='cmsRun' and self.command.find('cmsDriver.py')!=-1:
409  #Replacing 2>&1 |tee with >& in the shell command to preserve the return code significance:
410  # using tee return would be 0 even if the command failed before the pipe:
411  profiler_line='%s --prefix "%s" >& %s' %(self.command,valgrind_options,self.profile_name)
412 
413  else:
414  profiler_line='%s %s >& %s' %(valgrind_options,self.command,self.profile_name)
415  #'--trace-children=yes '+\
416  exec_status = execute(profiler_line)
417 
418  # compact the xml by removing the Leak_* errors
419  if not exec_status:
420  newFileName = xmlFileName.replace('valgrind.xml', 'vlgd.xml')
421  compactCmd = 'xsltproc --output %s %s/test/filterOutValgrindLeakErrors.xsl %s' %(newFileName, valperf, xmlFileName)
422  execute(compactCmd)
423 
424  return exec_status
def _profile_Memcheck_Valgrind(self)
def execute(command)
def cmsRelvalreport.Profile._profile_None (   self)
private
def cmsRelvalreport.Profile._profile_SimpleMem_Parser (   self)
private

Definition at line 432 of file cmsRelvalreport.py.

References cmsRelvalreport.Profile._save_output().

Referenced by cmsRelvalreport.Profile.make_profile().

433  return self._save_output()
434 
def cmsRelvalreport.Profile._profile_Timereport_Parser (   self)
private

Definition at line 427 of file cmsRelvalreport.py.

References cmsRelvalreport.Profile._save_output().

Referenced by cmsRelvalreport.Profile.make_profile().

428  return self._save_output()
429 
def _profile_Timereport_Parser(self)
def cmsRelvalreport.Profile._profile_Timing_Parser (   self)
private

Definition at line 437 of file cmsRelvalreport.py.

References cmsRelvalreport.Profile._save_output().

Referenced by cmsRelvalreport.Profile.make_profile().

438  return self._save_output()
439 
def cmsRelvalreport.Profile._profile_valgrindfce (   self)
private
Valgrind profile launcher.

Definition at line 305 of file cmsRelvalreport.py.

References runall.testit.command, cmsswPreprocessor.CmsswPreprocessor.command, WorkFlow.WorkFlowBlock.command, cmsRelvalreport.Profile.command, cmsRelvalreport.execute(), and cmsRelvalreport.Profile.profile_name.

Referenced by cmsRelvalreport.Profile.make_profile().

306  '''
307  Valgrind profile launcher.
308  '''
309  # ValgrindFCE needs a special library to run
310  os.environ["VALGRIND_LIB"]=VFCE_LIB
311 
312  profiler_line=''
313  valgrind_options= 'time valgrind '+\
314  '--tool=callgrind '+\
315  '--fce=%s ' %(self.profile_name)
316 
317  # If we are using cmsDriver we should use the prefix switch
318  if EXECUTABLE=='cmsRun' and self.command.find('cmsDriver.py')!=-1:
319  profiler_line='%s --prefix "%s"' %(self.command,valgrind_options)
320 
321  else:
322  profiler_line='%s %s' %(valgrind_options,self.command)
323  #'--trace-children=yes '+\
324 
325  return execute(profiler_line)
326 
def execute(command)
def cmsRelvalreport.Profile._save_output (   self)
private
Save the output of cmsRun on a file!

Definition at line 442 of file cmsRelvalreport.py.

References runall.testit.command, cmsswPreprocessor.CmsswPreprocessor.command, WorkFlow.WorkFlowBlock.command, cmsRelvalreport.Profile.command, cmsRelvalreport.execute(), and cmsRelvalreport.Profile.profile_name.

Referenced by cmsRelvalreport.Profile._profile_SimpleMem_Parser(), cmsRelvalreport.Profile._profile_Timereport_Parser(), and cmsRelvalreport.Profile._profile_Timing_Parser().

442  def _save_output(self):
443  '''
444  Save the output of cmsRun on a file!
445  '''
446 # # a first maquillage about the profilename:
447 # if self.profile_name[-4:]!='.log':
448 # self.profile_name+='.log'
449  #Replacing 2>&1 |tee with >& in the shell command to preserve the return code significance:
450  # using tee return would be 0 even if the command failed before the pipe:
451  profiler_line='%s >& %s' %(self.command,self.profile_name)
452  return execute(profiler_line)
453 
def execute(command)
def cmsRelvalreport.Profile.make_profile (   self)
Launch the right function according to the profiler name.

Definition at line 280 of file cmsRelvalreport.py.

References cmsRelvalreport.Profile._profile_edmsize(), cmsRelvalreport.Profile._profile_igprof(), cmsRelvalreport.Profile._profile_Memcheck_Valgrind(), cmsRelvalreport.Profile._profile_None(), cmsRelvalreport.Profile._profile_SimpleMem_Parser(), cmsRelvalreport.Profile._profile_Timereport_Parser(), cmsRelvalreport.Profile._profile_Timing_Parser(), cmsRelvalreport.Profile._profile_valgrindfce(), and cmsRelvalreport.Profile.profiler.

280  def make_profile(self):
281  '''
282  Launch the right function according to the profiler name.
283  '''
284  if self.profiler=='ValgrindFCE':
285  return self._profile_valgrindfce()
286  elif self.profiler.find('IgProf')!=-1:
287  return self._profile_igprof()
288  elif self.profiler.find('Edm_Size')!=-1:
289  return self._profile_edmsize()
290  elif self.profiler=='Memcheck_Valgrind':
291  return self._profile_Memcheck_Valgrind()
292  elif self.profiler=='Timereport_Parser':
293  return self._profile_Timereport_Parser()
294  elif self.profiler=='Timing_Parser':
295  return self._profile_Timing_Parser()
296  elif self.profiler=='SimpleMem_Parser':
297  return self._profile_SimpleMem_Parser()
298  elif self.profiler=='':
299  return self._profile_None()
300  elif self.profiler=='None': #adding this for the case of candle ASCII file non-profiling commands
301  return self._profile_None()
302  else:
303  raise 'No %s profiler found!'
def _profile_Timereport_Parser(self)
def _profile_Memcheck_Valgrind(self)
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 470 of file cmsRelvalreport.py.

References cmsRelvalreport.execute(), ALCARECOTkAlBeamHalo_cff.filter, createfilelist.int, cmsRelvalreport.Profile.profile_name, cmsRelvalreport.Profile.profiler, python.rootplot.root2matplotlib.replace(), split, and harvestTrackValidationPlots.str.

Referenced by cmsRelvalreport.Profile._profile_None().

470  metastring=None):
471  '''
472  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.
473  '''
474 
475  if outdir==None or outdir==self.profile_name:
476  outdir=self.profile_name+'_outdir'
477 
478  #Create the directory where the report will be stored:
479  if not os.path.exists(outdir) and not fill_db and not IgProf_option:
480  #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
481  execute('mkdir %s' %outdir)
482 
483  if fill_db:
484  db_option='-a'
485  if not os.path.exists(db_name):
486  db_option='-A'
487 
488  # temp in the local dir for PR
489  tmp_switch=''
490  if tmp_dir!='':
491  execute('mkdir %s' %tmp_dir)
492  tmp_switch=' -t %s' %tmp_dir
493 
494  #Handle the various profilers:
495 
496  #####################################################################
497 
498  # Profiler is ValgrindFCE:
499  if self.profiler=='ValgrindFCE':
500  perfreport_command=''
501  # Switch for filling the db
502  if not fill_db:
503  os.environ["PERFREPORT_PATH"]='%s/' %PERFREPORT2_PATH
504  perfreport_command='%s %s -ff -i %s -o %s' %(PR2,
505  tmp_switch,
506  self.profile_name,
507  outdir)
508  else:
509  os.environ["PERFREPORT_PATH"]='%s/' %PERFREPORT3_PATH
510  perfreport_command='%s %s -n5000 -u%s -ff -m \'scram_cmssw_version_string,%s\' -i %s %s -o %s' \
511  %(PR3,
512  tmp_switch,
513  PR3_PRODUCER_PLUGIN,
514  metastring,
515  self.profile_name,
516  db_option,
517  db_name)
518  return execute(perfreport_command)
519 
520  #####################################################################
521 
522  # Profiler is IgProf:
523  if self.profiler.find('IgProf')!=-1:
524  #First the case of IgProf PERF and MEM reporting:
525  if not 'ANALYSE' in IgProf_option:
526  #Switch to the use of igprof-analyse instead of PerfReport!
527  #Will use the ANALYSE case for regressions between early event dumps and late event dumps of the profiles
528  #Following Andreas suggestion, add the number of events for the EndOfJob report
529  NumberOfEvents=self.command.split()[3] #FIXME: this is quite hardcoded... but should be stable...
530  sqlite_outputfile=self.profile_name.split(".")[0].replace(IgProfProfiles[IgProf_option[0]],IgProf_option[0])+'___'+NumberOfEvents+'_EndOfJob.sql3'
531  logger("Executing the report of the IgProf end of job profile")
532  exit=execute('igprof-analyse --sqlite -d -v -g -r %s %s | sqlite3 %s'%(IgProf_option[0],self.profile_name,sqlite_outputfile))
533  return exit
534  #Then the "ANALYSE" case that we want to use to add to the same directories (Perf, MemTotal, MemLive)
535  #also some other analyses and in particular:
536  #1-the first 7 lines of the ASCII analysis of the IgProf profile dumps (total of the counters)
537  #2-the dump at different event numbers,
538  #3-the diff between the first and last dump,
539  #4-the counters grouped by library using regexp at the last dump:
540  else: #We use IgProf Analysis
541  #Set the IgProfCounter from the ANALYSE.MEM_TOT style IgProf_option
542  #print IgProf_option
543  IgProfCounter=IgProf_option[1]
544  #Add here the handling of the new IgProf.N.gz files so that they will get preserved and not overwritten:
545  logger("Looking for IgProf intermediate event profile dumps")
546  #Check if there are IgProf.N.gz dump files:
547  IgProfDumps=glob.glob("IgProf.*.gz")
548  #in case there are none check if they have already been mv'd to another name to avoid overwriting
549  #(MEM_LIVE usually re-uses MEM_TOTAL, so the IgProf.N.gz files will already have a MemTotal name...)
550  if not IgProfDumps:
551  localFiles=os.listdir('.')
552  IgProfDumpProfilesPrevious=re.compile(r"\w+.\d+.gz")
553  IgProfDumps=filter(lambda x: IgProfDumpProfilesPrevious.search(x),localFiles)
554  #Now if there are dumps execute the following analyses:
555  if IgProfDumps:
556  IgProfDumps.sort()
557  logger("Found the following IgProf intermediate event profile dumps:")
558  logger(IgProfDumps)
559  FirstDumpEvent=9999999
560  LastDumpEvent=0
561  exit=0
562  for dump in IgProfDumps:
563  if "___" in dump:
564  DumpEvent=dump.split(".")[0].split("___")[-1]
565  else:
566  DumpEvent=dump.split(".")[1]
567  #New naming convention using ___ as separator
568  DumpedProfileName=self.profile_name[:-3]+"___"+DumpEvent+".gz"
569  if dump.startswith("IgProf"):
570  execute('mv %s %s'%(dump,DumpedProfileName))
571  #Keep a tab of the first and last dump event for the diff analysis
572  if int(DumpEvent) < FirstDumpEvent:
573  FirstDumpEvent = int(DumpEvent)
574  if int(DumpEvent) > LastDumpEvent:
575  LastDumpEvent = int(DumpEvent)
576  #Eliminating the ASCII analysis to get the totals, Giulio will provide this information in igprof-navigator with a special query
577  #First type of analysis: dump first 7 lines of ASCII analysis:
578  #logger("Executing the igprof-analyse analysis to dump the ASCII 7 lines output with the totals for the IgProf counter")
579  #exit=execute('%s -o%s -i%s -t%s' %(IGPROFANALYS,outdir,DumpedProfileName,"ASCII"))
580  #Second type of analysis: dump the report in sqlite format to be ready to be browsed with igprof-navigator
581  logger("Executing the igprof-analyse analysis saving into igprof-navigator browseable SQLite3 format")
582  #exit=exit+execute('%s -o%s -i%s -t%s' %(IGPROFANALYS,outdir,DumpedProfileName,"SQLite3"))
583  #Execute all types of analyses available with the current profile (using the dictionary IgProfProfile):
584  #To avoid this we should use a further input in SimulationCandles.txt IgProfMem.ANALYSE.MEM_TOTAL maybe the cleanest solution.
585  #for IgProfile in IgProfCounters.keys():
586  # if DumpedProfileName.find(IgProfile)>0:
587  # for counter in IgProfCounters[IgProfile]:
588  #Check that the file does not exist:
589  #if not os.path.exists(DumpedProfileName.split(".")[0].replace(IgProfProfiles[counter],counter)+".sql3"):
590  exit=exit+execute('%s -c%s -i%s -t%s' %(IGPROFANALYS,IgProfCounter,DumpedProfileName,"SQLite3"))
591  #else:
592  # print "File %s already exists will not process profile"%DumpedProfileName.split(".")[0].replace(IgProfProfiles[counter],counter)+".sql3"
593  #FIXME:
594  #Issue with multiple profiles in the same dir: assuming Perf and Mem will always be in separate dirs
595  #Potential ssue with multiple steps?
596  #Adapting to new igprof naming scheme:
597  FirstDumpProfile=self.profile_name[:-3]+"___"+str(FirstDumpEvent)+".gz"
598  LastDumpProfile=self.profile_name[:-3]+"___"+str(LastDumpEvent)+".gz"
599  #Third type of analysis: execute the diff analysis:
600  #Check there are at least 2 IgProf intermediate event dump profiles to do a regression!
601  if len(IgProfDumps)>1:
602  logger("Executing the igprof-analyse regression between the first IgProf profile dump and the last one")
603  #for IgProfile in IgProfCounters.keys():
604  # if DumpedProfileName.find(IgProfile)>0:
605  # IgProfCounter=IgProfCounters[IgProfile]
606  exit=exit+execute('%s -c%s -i%s -r%s' %(IGPROFANALYS,IgProfCounter,LastDumpProfile,FirstDumpProfile))
607  else:
608  logger("CANNOT execute any regressions: not enough IgProf intermediate event profile dumps!")
609  #Fourth type of analysis: execute the grouped by library igprof-analyse:
610  logger("Executing the igprof-analyse analysis merging the results by library via regexp and saving the result in igprof-navigator browseable SQLite3 format")
611  #for IgProfile in IgProfCounters.keys():
612  # if DumpedProfileName.find(IgProfile)>0:
613  # IgProfCounter=IgProfCounters[IgProfile]
614  exit=exit+execute('%s -c%s -i%s --library' %(IGPROFANALYS,IgProfCounter,LastDumpProfile))
615  #If they are not there at all (no dumps)
616  else:
617  logger("No IgProf intermediate event profile dumps found!")
618  exit=0
619 
620  return exit
621 
622 
623  #####################################################################
624 
625  # Profiler is EdmSize:
626  if 'Edm_Size' in self.profiler:
627  perfreport_command=''
628  if not fill_db:
629  os.environ["PERFREPORT_PATH"]='%s/' \
630  %PERFREPORT2_PATH
631  perfreport_command='%s %s -fe -i %s -o %s' \
632  %(PR2,
633  tmp_switch,
634  self.profile_name,
635  outdir)
636  else:
637  os.environ["PERFREPORT_PATH"]='%s/' \
638  %PERFREPORT3_PATH
639  perfreport_command='%s %s -n5000 -u%s -fe -i %s -a -o %s' \
640  %(PR3,
641  tmp_switch,
642  PR3_PRODUCER_PLUGIN,
643  self.profile_name,
644  db_name)
645 
646  return execute(perfreport_command)
647 
648  #FIXME: probably need to move this somewhere else now that we use return statements
649  if tmp_dir!='':
650  execute('rm -r %s' %tmp_dir)
651 
652  #####################################################################
653 
654  # Profiler is Valgrind Memcheck
655  if self.profiler=='Memcheck_Valgrind':
656  # Three pages will be produced:
657  os.environ['PERL5LIB']=PERL5_LIB
658  report_coordinates=(VMPARSER,self.profile_name,outdir)
659  # Copy the Valgrind Memcheck parser style file in the outdir
660  copyStyleFile='cp -pR %s %s'%(VMPARSERSTYLE,outdir)
661  execute(copyStyleFile)
662  report_commands=('%s --preset +prod,-prod1 %s > %s/edproduce.html'\
663  %report_coordinates,
664  '%s --preset +prod1 %s > %s/esproduce.html'\
665  %report_coordinates,
666  '%s -t beginJob %s > %s/beginjob.html'\
667  %report_coordinates)
668  exit=0
669  for command in report_commands:
670  exit= exit + execute(command)
671  return exit
672  #####################################################################
673 
674  # Profiler is TimeReport parser
675 
676  if self.profiler=='Timereport_Parser':
677  return execute('%s %s %s' %(TIMEREPORTPARSER,self.profile_name,outdir))
678 
679  #####################################################################
680 
681  # Profiler is Timing Parser
682 
683  if self.profiler=='Timing_Parser':
684  return execute('%s -i %s -o %s' %(TIMINGPARSER,self.profile_name,outdir))
685 
686 
687  #####################################################################
688 
689  # Profiler is Simple memory parser
690 
691  if self.profiler=='SimpleMem_Parser':
692  return execute('%s -i %s -o %s' %(SIMPLEMEMPARSER,self.profile_name,outdir))
693 
694  #####################################################################
695 
696  # no profiler
697 
698  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).
699  return 0 #Used to be pass, but we need a return 0 to handle exit code properly!
700 
def replace(string, replacements)
Definition: logger.py:1
def execute(command)
double split
Definition: MVATrainer.cc:139

Member Data Documentation

cmsRelvalreport.Profile.command
cmsRelvalreport.Profile.profile_name
cmsRelvalreport.Profile.profiler