6565
6666class Target :
6767 """Represents a single line read for a .ninja_log file."""
68+
6869 def __init__ (self , start , end ):
6970 """Creates a target object by passing in the start/end times in seconds
7071 as a float."""
@@ -94,20 +95,20 @@ def WeightedDuration(self):
9495 """
9596 # Allow for modest floating-point errors
9697 epsilon = 0.000002
97- if ( self .weighted_duration > self .Duration () + epsilon ) :
98- print (' %s > %s?' % (self .weighted_duration , self .Duration ()))
99- assert ( self .weighted_duration <= self .Duration () + epsilon )
98+ if self .weighted_duration > self .Duration () + epsilon :
99+ print (" %s > %s?" % (self .weighted_duration , self .Duration ()))
100+ assert self .weighted_duration <= self .Duration () + epsilon
100101 return self .weighted_duration
101102
102103 def DescribeTargets (self ):
103104 """Returns a printable string that summarizes the targets."""
104105 # Some build steps generate dozens of outputs - handle them sanely.
105106 # The max_length was chosen so that it can fit most of the long
106107 # single-target names, while minimizing word wrapping.
107- result = ', ' .join (self .targets )
108+ result = ", " .join (self .targets )
108109 max_length = 65
109110 if len (result ) > max_length :
110- result = result [:max_length ] + ' ...'
111+ result = result [:max_length ] + " ..."
111112 return result
112113
113114
@@ -121,12 +122,11 @@ def ReadTargets(log, show_all):
121122 # targets.
122123 if not header :
123124 return []
124- assert header == '# ninja log v5\n ' , \
125- 'unrecognized ninja log version %r' % header
125+ assert header == "# ninja log v5\n " , "unrecognized ninja log version %r" % header
126126 targets_dict = {}
127127 last_end_seen = 0.0
128128 for line in log :
129- parts = line .strip ().split (' \t ' )
129+ parts = line .strip ().split (" \t " )
130130 if len (parts ) != 5 :
131131 # If ninja.exe is rudely halted then the .ninja_log file may be
132132 # corrupt. Silently continue.
@@ -165,17 +165,17 @@ def ReadTargets(log, show_all):
165165def GetExtension (target , extra_patterns ):
166166 """Return the file extension that best represents a target.
167167
168- For targets that generate multiple outputs it is important to return a
169- consistent 'canonical' extension. Ultimately the goal is to group build steps
170- by type."""
168+ For targets that generate multiple outputs it is important to return a
169+ consistent 'canonical' extension. Ultimately the goal is to group build steps
170+ by type."""
171171 for output in target .targets :
172172 if extra_patterns :
173- for fn_pattern in extra_patterns .split (';' ):
174- if fnmatch .fnmatch (output , '*' + fn_pattern + '*' ):
173+ for fn_pattern in extra_patterns .split (";" ):
174+ if fnmatch .fnmatch (output , "*" + fn_pattern + "*" ):
175175 return fn_pattern
176176 # Not a true extension, but a good grouping.
177- if output .endswith (' type_mappings' ):
178- extension = ' type_mappings'
177+ if output .endswith (" type_mappings" ):
178+ extension = " type_mappings"
179179 break
180180
181181 # Capture two extensions if present. For example: file.javac.jar should
@@ -185,26 +185,26 @@ def GetExtension(target, extra_patterns):
185185 extension = ext2 + ext1 # Preserve the order in the file name.
186186
187187 if len (extension ) == 0 :
188- extension = ' (no extension found)'
188+ extension = " (no extension found)"
189189
190- if ext1 in [' .pdb' , ' .dll' , ' .exe' ]:
191- extension = ' PEFile (linking)'
190+ if ext1 in [" .pdb" , " .dll" , " .exe" ]:
191+ extension = " PEFile (linking)"
192192 # Make sure that .dll and .exe are grouped together and that the
193193 # .dll.lib files don't cause these to be listed as libraries
194194 break
195- if ext1 in [' .so' , ' .TOC' ]:
196- extension = ' .so (linking)'
195+ if ext1 in [" .so" , " .TOC" ]:
196+ extension = " .so (linking)"
197197 # Attempt to identify linking, avoid identifying as '.TOC'
198198 break
199199 # Make sure .obj files don't get categorized as mojo files
200- if ext1 in [' .obj' , '.o' ]:
200+ if ext1 in [" .obj" , ".o" ]:
201201 break
202202 # Jars are the canonical output of java targets.
203- if ext1 == ' .jar' :
203+ if ext1 == " .jar" :
204204 break
205205 # Normalize all mojo related outputs to 'mojo'.
206- if output .count (' .mojom' ) > 0 :
207- extension = ' mojo'
206+ if output .count (" .mojom" ) > 0 :
207+ extension = " mojo"
208208 break
209209 return extension
210210
@@ -229,8 +229,8 @@ def SummarizeEntries(entries, extra_step_types, elapsed_time_sorting):
229229 if target .end > latest :
230230 latest = target .end
231231 total_cpu_time += target .Duration ()
232- task_start_stop_times .append ((target .start , ' start' , target ))
233- task_start_stop_times .append ((target .end , ' stop' , target ))
232+ task_start_stop_times .append ((target .start , " start" , target ))
233+ task_start_stop_times .append ((target .end , " stop" , target ))
234234 length = latest - earliest
235235 weighted_total = 0.0
236236
@@ -256,35 +256,38 @@ def SummarizeEntries(entries, extra_step_types, elapsed_time_sorting):
256256 if num_running > 0 :
257257 # Update the total weighted time up to this moment.
258258 last_weighted_time += (time - last_time ) / float (num_running )
259- if action_name == ' start' :
259+ if action_name == " start" :
260260 # Record the total weighted task time when this task starts.
261261 running_tasks [target ] = last_weighted_time
262- if action_name == ' stop' :
262+ if action_name == " stop" :
263263 # Record the change in the total weighted task time while this task
264264 # ran.
265265 weighted_duration = last_weighted_time - running_tasks [target ]
266266 target .SetWeightedDuration (weighted_duration )
267267 weighted_total += weighted_duration
268268 del running_tasks [target ]
269269 last_time = time
270- assert ( len (running_tasks ) == 0 )
270+ assert len (running_tasks ) == 0
271271
272272 # Warn if the sum of weighted times is off by more than half a second.
273273 if abs (length - weighted_total ) > 500 :
274- print ('Warning: Possible corrupt ninja log, results may be '
275- 'untrustworthy. Length = %.3f, weighted total = %.3f' %
276- (length , weighted_total ))
274+ print (
275+ "Warning: Possible corrupt ninja log, results may be "
276+ "untrustworthy. Length = %.3f, weighted total = %.3f"
277+ % (length , weighted_total )
278+ )
277279
278280 # Print the slowest build steps:
279- print (' Longest build steps:' )
281+ print (" Longest build steps:" )
280282 if elapsed_time_sorting :
281283 entries .sort (key = lambda x : x .Duration ())
282284 else :
283285 entries .sort (key = lambda x : x .WeightedDuration ())
284286 for target in entries [- long_count :]:
285- print (' %8.1f weighted s to build %s (%.1f s elapsed time)' %
286- (target .WeightedDuration (), target .DescribeTargets (),
287- target .Duration ()))
287+ print (
288+ " %8.1f weighted s to build %s (%.1f s elapsed time)"
289+ % (target .WeightedDuration (), target .DescribeTargets (), target .Duration ())
290+ )
288291
289292 # Sum up the time by file extension/type of the output file
290293 count_by_ext = {}
@@ -293,51 +296,56 @@ def SummarizeEntries(entries, extra_step_types, elapsed_time_sorting):
293296 # Scan through all of the targets to build up per-extension statistics.
294297 for target in entries :
295298 extension = GetExtension (target , extra_step_types )
296- time_by_ext [extension ] = time_by_ext .get (extension ,
297- 0 ) + target . Duration ()
298- weighted_time_by_ext [ extension ] = weighted_time_by_ext .get (
299- extension , 0 ) + target . WeightedDuration ( )
299+ time_by_ext [extension ] = time_by_ext .get (extension , 0 ) + target . Duration ()
300+ weighted_time_by_ext [ extension ] = (
301+ weighted_time_by_ext .get (extension , 0 ) + target . WeightedDuration ()
302+ )
300303 count_by_ext [extension ] = count_by_ext .get (extension , 0 ) + 1
301304
302- print (' Time by build-step type:' )
305+ print (" Time by build-step type:" )
303306 # Copy to a list with extension name and total time swapped, to (time, ext)
304307 if elapsed_time_sorting :
305- weighted_time_by_ext_sorted = sorted (
306- (y , x ) for (x , y ) in time_by_ext .items ())
308+ weighted_time_by_ext_sorted = sorted ((y , x ) for (x , y ) in time_by_ext .items ())
307309 else :
308310 weighted_time_by_ext_sorted = sorted (
309- (y , x ) for (x , y ) in weighted_time_by_ext .items ())
311+ (y , x ) for (x , y ) in weighted_time_by_ext .items ()
312+ )
310313 # Print the slowest build target types:
311314 for time , extension in weighted_time_by_ext_sorted [- long_ext_count :]:
312315 print (
313- ' %8.1f s weighted time to generate %d %s files '
314- '(%1.1f s elapsed time sum)' %
315- (time , count_by_ext [extension ], extension , time_by_ext [extension ]))
316+ " %8.1f s weighted time to generate %d %s files "
317+ "(%1.1f s elapsed time sum)"
318+ % (time , count_by_ext [extension ], extension , time_by_ext [extension ])
319+ )
316320
317- print (' %.1f s weighted time (%.1f s elapsed time sum, %1.1fx '
318- 'parallelism)' %
319- (length , total_cpu_time , total_cpu_time * 1.0 / length ))
320- print (' %d build steps completed, average of %1.2f/s' %
321- (len (entries ), len (entries ) / (length )))
321+ print (
322+ " %.1f s weighted time (%.1f s elapsed time sum, %1.1fx "
323+ "parallelism)" % (length , total_cpu_time , total_cpu_time * 1.0 / length )
324+ )
325+ print (
326+ " %d build steps completed, average of %1.2f/s"
327+ % (len (entries ), len (entries ) / (length ))
328+ )
322329
323330
324331def main ():
325- log_file = ' .ninja_log'
326- metrics_file = ' siso_metrics.json'
332+ log_file = " .ninja_log"
333+ metrics_file = " siso_metrics.json"
327334 parser = argparse .ArgumentParser ()
328- parser .add_argument ('-C' , dest = ' build_directory' , help = ' Build directory.' )
335+ parser .add_argument ("-C" , dest = " build_directory" , help = " Build directory." )
329336 parser .add_argument (
330- '-s' ,
331- '--step-types' ,
332- help = 'semicolon separated fnmatch patterns for build-step grouping' )
337+ "-s" ,
338+ "--step-types" ,
339+ help = "semicolon separated fnmatch patterns for build-step grouping" ,
340+ )
333341 parser .add_argument (
334- '-e' ,
335- ' --elapsed_time_sorting' ,
342+ "-e" ,
343+ " --elapsed_time_sorting" ,
336344 default = False ,
337- action = ' store_true' ,
338- help = ' Sort output by elapsed time instead of weighted time' )
339- parser . add_argument ( '--log-file' ,
340- help = "specific ninja log file to analyze." )
345+ action = " store_true" ,
346+ help = " Sort output by elapsed time instead of weighted time" ,
347+ )
348+ parser . add_argument ( "--log-file" , help = "specific ninja log file to analyze." )
341349 args , _extra_args = parser .parse_known_args ()
342350 if args .build_directory :
343351 log_file = os .path .join (args .build_directory , log_file )
@@ -348,34 +356,35 @@ def main():
348356 # Offer a convenient way to add extra step types automatically,
349357 # including when this script is run by autoninja. get() returns None if
350358 # the variable isn't set.
351- args .step_types = os .environ .get (' chromium_step_types' )
359+ args .step_types = os .environ .get (" chromium_step_types" )
352360 if args .step_types :
353361 # Make room for the extra build types.
354362 global long_ext_count
355- long_ext_count += len (args .step_types .split (';' ))
363+ long_ext_count += len (args .step_types .split (";" ))
356364
357365 if os .path .exists (metrics_file ):
358366 # Automatically handle summarizing siso builds.
359- cmd = [' siso.bat' if ' win32' in sys .platform else ' siso' ]
360- cmd .extend ([' metrics' , ' summary' ])
367+ cmd = [" siso.bat" if " win32" in sys .platform else " siso" ]
368+ cmd .extend ([" metrics" , " summary" ])
361369 if args .build_directory :
362- cmd .extend (['-C' , args .build_directory ])
370+ cmd .extend (["-C" , args .build_directory ])
363371 if args .step_types :
364- cmd .extend ([' --step_types' , args .step_types ])
372+ cmd .extend ([" --step_types" , args .step_types ])
365373 if args .elapsed_time_sorting :
366- cmd .append (' --elapsed_time_sorting' )
374+ cmd .append (" --elapsed_time_sorting" )
367375 subprocess .run (cmd )
368376 else :
369377 try :
370- with open (log_file , 'r' ) as log :
378+ with open (log_file , "r" ) as log :
371379 entries = ReadTargets (log , False )
372380 if entries :
373- SummarizeEntries (entries , args .step_types ,
374- args .elapsed_time_sorting )
381+ SummarizeEntries (
382+ entries , args .step_types , args .elapsed_time_sorting
383+ )
375384 except IOError :
376- print (' Log file %r not found, no build summary created.' % log_file )
385+ print (" Log file %r not found, no build summary created." % log_file )
377386 return errno .ENOENT
378387
379388
380- if __name__ == ' __main__' :
389+ if __name__ == " __main__" :
381390 sys .exit (main ())
0 commit comments