@@ -19,29 +19,29 @@ def printHelp():
1919 This script will output a more human readable form of the data in the log file.'''
2020 return s
2121
22- #these values come from moduleALloc_setupFile .cc
23- #enum class Step : char {
24- # preSourceTransition = 'S',
25- # postSourceTransition = 's',
26- # preModulePrefetching = 'P',
27- # postModulePrefetching = 'p',
28- # preModuleEventAcquire = 'A',
29- # postModuleEventAcquire = 'a',
30- # preModuleTransition = 'M',
31- # preEventReadFromSource = 'R',
32- # postEventReadFromSource = 'r',
33- # preModuleEventDelayedGet = 'D',
34- # postModuleEventDelayedGet = 'd',
35- # postModuleTransition = 'm',
36- # preESModulePrefetching = 'Q',
37- # postESModulePrefetching = 'q',
38- # preESModule = 'N',
39- # postESModule = 'n',
40- # preESModuleAcquire = 'B',
41- # postESModuleAcquire = 'b',
42- # preFrameworkTransition = 'F',
43- # postFrameworkTransition = 'f'
44- #};
22+ # These values come from moduleAlloc_setupFile .cc
23+ # enum class Step : char {
24+ # preSourceTransition = 'S',
25+ # postSourceTransition = 's',
26+ # preModulePrefetching = 'P',
27+ # postModulePrefetching = 'p',
28+ # preModuleEventAcquire = 'A',
29+ # postModuleEventAcquire = 'a',
30+ # preModuleTransition = 'M',
31+ # preEventReadFromSource = 'R',
32+ # postEventReadFromSource = 'r',
33+ # preModuleEventDelayedGet = 'D',
34+ # postModuleEventDelayedGet = 'd',
35+ # postModuleTransition = 'm',
36+ # preESModulePrefetching = 'Q',
37+ # postESModulePrefetching = 'q',
38+ # preESModule = 'N',
39+ # postESModule = 'n',
40+ # preESModuleAcquire = 'B',
41+ # postESModuleAcquire = 'b',
42+ # preFrameworkTransition = 'F',
43+ # postFrameworkTransition = 'f'
44+ # };
4545
4646
4747kMicroToSec = 0.000001
@@ -192,6 +192,16 @@ def textPrefix_(time, indentLevel):
192192 return f'{ time :>11} ' + "++" * indentLevel
193193
194194class AllocInfo (object ):
195+ """Container for memory allocation information from CMSSW module transitions.
196+
197+ Attributes:
198+ nAllocs: Number of memory allocations
199+ nDeallocs: Number of memory deallocations
200+ added: Net memory added (in bytes)
201+ minTemp: Minimum temporary memory usage
202+ maxTemp: Maximum temporary memory usage
203+ max1Alloc: Largest single allocation
204+ """
195205 def __init__ (self ,payload ):
196206 self .nAllocs = int (payload [0 ])
197207 self .nDeallocs = int (payload [1 ])
@@ -333,6 +343,7 @@ def toSimpleDict(self):
333343 l = None
334344 if m == 'source' :
335345 l = dct ['source' ]
346+ cpptypes [m ]= self ._cpptypes [m ]
336347 elif m == 'clearEvent' :
337348 l = dct ['clearEvent' ]
338349 else :
@@ -526,7 +537,7 @@ def jsonVisInfo(self, data):
526537
527538
528539class SourceTransitionParser (object ):
529- def __init__ (self , payload ):
540+ def __init__ (self , payload , sourceInfos ):
530541 self .transition = int (payload [0 ])
531542 if self .transition == Phase .getNextTransition :
532543 self .time = int (payload [1 ])
@@ -556,9 +567,10 @@ def text(self, context):
556567 return f'{ self .textPrefix ()} { self .textSpecial ()} : { self .textPostfix ()} '
557568
558569class PreSourceTransitionParser (SourceTransitionParser ):
559- def __init__ (self , payload , moduleCentric ):
570+ def __init__ (self , payload , sourceInfos , moduleCentric ):
560571 self ._moduleCentric = moduleCentric
561- super ().__init__ (payload )
572+ super ().__init__ (payload , sourceInfos )
573+ self ._sourceInfo = sourceInfos [0 ]
562574 def textSpecial (self ):
563575 return "starting"
564576 def jsonInfo (self , syncs , temp , data ):
@@ -607,22 +619,23 @@ def jsonVisInfo(self, data):
607619 data .findOpenSlotInModGlobals (index ,0 ).append (container [- 1 ])
608620
609621class PostSourceTransitionParser (SourceTransitionParser ):
610- def __init__ (self , payload , moduleCentric ):
611- super ().__init__ (payload )
622+ def __init__ (self , payload , sourceInfos , moduleCentric ):
623+ super ().__init__ (payload , sourceInfos )
612624 if self .index == - 1 :
613625 self .allocInfo = AllocInfo (payload [2 :])
614626 else :
615627 self .allocInfo = AllocInfo (payload [3 :])
616628 self ._moduleCentric = moduleCentric
629+ self ._sourceInfo = sourceInfos [0 ]
617630 def textSpecial (self ):
618631 return "finished"
619632 def jsonInfo (self , syncs , temp , data ):
620633 start = temp .findTime ("source" , self .transition , self .index )
621634 #we do not know the sync yet so have to wait until the framework transition
622635 if self .transition in [ Phase .construction , Phase .getNextTransition , Phase .destruction , Phase .openFile ]:
623- data .insert ( "source" , "PoolSource" , start , self .time , self .transition , self .index , (0 ,) , Activity .process , self .allocInfo )
636+ data .insert ( "source" , self . _sourceInfo . _cpptype , start , self .time , self .transition , self .index , (0 ,) , Activity .process , self .allocInfo )
624637 else :
625- data .insert ( "source" , "PoolSource" , start , self .time , self .transition , self .index , self .index , Activity .process , self .allocInfo )
638+ data .insert ( "source" , self . _sourceInfo . _cpptype , start , self .time , self .transition , self .index , self .index , Activity .process , self .allocInfo )
626639 def jsonVisInfo (self , data ):
627640 index = self .index
628641 if self .transition == Phase .Event :
@@ -812,7 +825,7 @@ def jsonVisInfo(self, data):
812825 return self ._postJsonVis (data , self .allocInfo )
813826 def jsonInfo (self , syncs , temp , data ):
814827 start = temp .findTime (self .moduleInfo ._name + 'source' , self .transition , self .index )
815- data .insert ( "source" , "PoolSource" , start , self .time , self .transition , self .index , syncs .get (self .transition , self .index ) , Activity .delayedGet , self .allocInfo )
828+ data .insert ( "source" , self . moduleInfo . _cpptype , start , self .time , self .transition , self .index , syncs .get (self .transition , self .index ) , Activity .delayedGet , self .allocInfo )
816829
817830class ESModuleTransitionParser (object ):
818831 def __init__ (self , payload , moduleInfos , esModuleInfos , recordNames ):
@@ -900,16 +913,16 @@ def jsonVisInfo(self, data):
900913 return self ._postJsonVis (data , self .allocInfo )
901914
902915
903- def lineParserFactory (step , payload , moduleInfos , esModuleInfos , recordNames , moduleCentric ):
916+ def lineParserFactory (step , payload , moduleInfos , esModuleInfos , sourceInfos , recordNames , moduleCentric ):
904917 if step == 'F' :
905918 parser = PreFrameworkTransitionParser (payload )
906919 return parser
907920 if step == 'f' :
908921 return PostFrameworkTransitionParser (payload )
909922 if step == 'S' :
910- return PreSourceTransitionParser (payload , moduleCentric )
923+ return PreSourceTransitionParser (payload , sourceInfos , moduleCentric )
911924 if step == 's' :
912- return PostSourceTransitionParser (payload , moduleCentric )
925+ return PostSourceTransitionParser (payload , sourceInfos , moduleCentric )
913926 if step == 'M' :
914927 return PreEDModuleTransitionParser (payload , moduleInfos , moduleCentric )
915928 if step == 'm' :
@@ -934,18 +947,18 @@ def lineParserFactory (step, payload, moduleInfos, esModuleInfos, recordNames, m
934947 return PreESModuleAcquireParser (payload , moduleInfos , esModuleInfos , recordNames )
935948 if step == 'b' :
936949 return PostESModuleAcquireParser (payload , moduleInfos , esModuleInfos , recordNames )
937- raise LogicError ("Unknown step '{}'" .format (step ))
950+ raise ValueError ("Unknown step '{}'" .format (step ))
938951
939952#----------------------------------------------
940- def processingStepsFromFile (f , moduleInfos , esModuleInfos , recordNames , moduleCentric ):
953+ def processingStepsFromFile (f , moduleInfos , esModuleInfos , sourceInfos , recordNames , moduleCentric ):
941954 for rawl in f :
942955 l = rawl .strip ()
943956 if not l or l [0 ] == '#' :
944957 continue
945958 (step ,payload ) = tuple (l .split (None ,1 ))
946959 payload = payload .split ()
947960
948- parser = lineParserFactory (step , payload , moduleInfos , esModuleInfos , recordNames , moduleCentric )
961+ parser = lineParserFactory (step , payload , moduleInfos , esModuleInfos , sourceInfos , recordNames , moduleCentric )
949962 if parser :
950963 yield parser
951964 return
@@ -958,6 +971,7 @@ def __init__(self,f, moduleCentric):
958971 moduleInfos = {}
959972 esModuleInfos = {}
960973 recordNames = {}
974+ sourceInfos = {}
961975 for rawl in f :
962976 l = rawl .strip ()
963977 if l and l [0 ] == 'M' :
@@ -978,6 +992,10 @@ def __init__(self,f, moduleCentric):
978992 (id ,name ,mType )= tuple (l [2 :].split ())
979993 esModuleInfos [int (id )] = ModuleInfo (name ,mType )
980994 continue
995+ if len (l ) > 5 and l [0 :2 ] == "#S" :
996+ (id ,name ,sType )= tuple (l [2 :].split ())
997+ sourceInfos [0 ] = ModuleInfo (name ,sType )
998+ continue
981999 if len (l ) > 5 and l [0 :2 ] == "#R" :
9821000 (id ,name )= tuple (l [2 :].split ())
9831001 recordNames [int (id )] = name
@@ -990,6 +1008,7 @@ def __init__(self,f, moduleCentric):
9901008 self .numStreams = numStreams
9911009 self ._moduleInfos = moduleInfos
9921010 self ._esModuleInfos = esModuleInfos
1011+ self ._sourceInfos = sourceInfos
9931012 self ._recordNames = recordNames
9941013 self .maxNameSize = 0
9951014 for n in moduleInfos .items ():
@@ -1004,12 +1023,21 @@ def processingSteps(self):
10041023 Using a generator reduces the memory overhead when parsing a large file.
10051024 """
10061025 self ._f .seek (0 )
1007- return processingStepsFromFile (self ._f ,self ._moduleInfos , self ._esModuleInfos , self ._recordNames , self ._moduleCentric )
1026+ return processingStepsFromFile (self ._f ,self ._moduleInfos , self ._esModuleInfos , self ._sourceInfos , self . _recordNames , self ._moduleCentric )
10081027
10091028def textOutput ( parser ):
10101029 context = {}
10111030 for p in parser .processingSteps ():
10121031 print (p .text (context ))
1032+
1033+ def showSourceTypes ( parser ):
1034+ print ("Source Module Types:" )
1035+ print ("===================" )
1036+ if hasattr (parser , '_sourceInfos' ) and parser ._sourceInfos :
1037+ for id , info in parser ._sourceInfos .items ():
1038+ print (f" Source ID { id } : { info ._name } (type: { info ._cpptype } )" )
1039+ else :
1040+ print (" No source module types found in log file." )
10131041
10141042class VisualizationContainers (object ):
10151043 def __init__ (self ):
@@ -1281,7 +1309,7 @@ def jsonVisualizationInfo(parser):
12811309 time += t ["finish" ]- t ["start" ]
12821310 modules [- 1 ]['time' ]= time
12831311 modules .sort (key = lambda x : x ['time' ], reverse = True )
1284- final ['transitions' ].append ({"name" : "source" , "slots" :sourceSlot })
1312+ final ['transitions' ].append ({"name" : "source" , "cpptype" : parser . _sourceInfos [ 0 ]. _cpptype , " slots" :sourceSlot })
12851313 for m in modules :
12861314 final ['transitions' ].append (m )
12871315
@@ -1327,6 +1355,7 @@ def incr(t):
13271355 '#R 1 Record' ,
13281356 '#M 1 Module ModuleType' ,
13291357 '#N 1 ESModule ESModuleType' ,
1358+ '#S 1 Source SourceType' ,
13301359 f'F { Phase .startTracing } 0 0 0 0 { incr (t )} ' ,
13311360 f'S { Phase .construction } 0 { incr (t )} ' ,
13321361 f's { Phase .construction } 0 { incr (t )} 1 1 10 0 10 10' ,
@@ -1493,6 +1522,7 @@ def runTests():
14931522 formatter_class = argparse .RawDescriptionHelpFormatter ,
14941523 epilog = printHelp ())
14951524 parser .add_argument ('filename' ,
1525+ nargs = '?' , # Make filename optional
14961526 type = argparse .FileType ('r' ), # open file
14971527 help = 'file to process' )
14981528 parser .add_argument ('-j' , '--json' ,
@@ -1501,7 +1531,7 @@ def runTests():
15011531 parser .add_argument ('-s' , '--sortBy' ,
15021532 default = '' ,
15031533 type = str ,
1504- help = "sort modules by attribute. Alloed values 'nAllocs', 'nDeallocs', 'added', 'minTemp', maxTemp', and 'max1Alloc'" )
1534+ help = "sort modules by attribute. Allowed values 'nAllocs', 'nDeallocs', 'added', 'minTemp', ' maxTemp', and 'max1Alloc'" )
15051535# parser.add_argument('-w', '--web',
15061536# action='store_true',
15071537# help='''Writes data.js file that can be used with the web based inspector. To use, copy directory ${CMSSW_RELEASE_BASE}/src/FWCore/Services/template/web to a web accessible area and move data.js into that directory.''')
@@ -1511,11 +1541,17 @@ def runTests():
15111541 parser .add_argument ('-T' , '--test' ,
15121542 action = 'store_true' ,
15131543 help = '''Run internal tests.''' )
1544+ parser .add_argument ('--showSourceTypes' ,
1545+ action = 'store_true' ,
1546+ help = '''Display source module types.''' )
15141547
15151548 args = parser .parse_args ()
15161549
15171550 if args .test :
15181551 runTests ()
1552+ elif args .filename is None :
1553+ parser .print_help ()
1554+ sys .exit (1 )
15191555 else :
15201556 parser = ModuleAllocCompactFileParser (args .filename , not args .timeOrdered )
15211557# if args.json or args.web:
@@ -1528,5 +1564,7 @@ def runTests():
15281564# f.close()
15291565 elif args .sortBy :
15301566 print (json .dumps (sortByAttribute (parser , args .sortBy ), indent = 2 ))
1567+ elif args .showSourceTypes :
1568+ showSourceTypes (parser )
15311569 else :
15321570 textOutput (parser )
0 commit comments