Commit 34d90beb authored by Bruce Dawson's avatar Bruce Dawson Committed by LUCI CQ

Allow customizable build-type grouping

The post_build_ninja_summary.py script, which autoninja automatically
runs if NINJA_SUMMARIZE_BUILD=1 is set, summarizes build time by file
extension. This is a good default summary but it can be handy to create
additional output categories. This change allows using fn_match style
wildcards to create additional categories which will then be summarized.
For instance:

  python post_build_ninja_summary.py -C out/Def -s prec*.obj;blink*.obj

In addition the chromium_step_types environment variable can be set so
that when autoninja runs this script there will be additional summary
categories.

This has been used most recently when measuring the cost of creating and
using blink precompiled header files.

Bug: 1061326
Change-Id: I080b4ddd06d045a2351220e202cd9eec111bf00e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2093145
Auto-Submit: Bruce Dawson <brucedawson@chromium.org>
Reviewed-by: 's avatarEdward Lesmes <ehmaldonado@chromium.org>
Commit-Queue: Bruce Dawson <brucedawson@chromium.org>
parent 8cf12290
......@@ -55,6 +55,7 @@ from __future__ import print_function
import argparse
import errno
import fnmatch
import os
import sys
......@@ -163,13 +164,17 @@ def ReadTargets(log, show_all):
return targets_dict.values()
def GetExtension(target):
def GetExtension(target, extra_patterns):
"""Return the file extension that best represents a target.
For targets that generate multiple outputs it is important to return a
consistent 'canonical' extension. Ultimately the goal is to group build steps
by type."""
for output in target.targets:
if extra_patterns:
for fn_pattern in extra_patterns.split(';'):
if fnmatch.fnmatch(output, '*' + fn_pattern + '*'):
return fn_pattern
# Not a true extension, but a good grouping.
if output.endswith('type_mappings'):
extension = 'type_mappings'
......@@ -196,7 +201,7 @@ def GetExtension(target):
return extension
def SummarizeEntries(entries):
def SummarizeEntries(entries, extra_step_types):
"""Print a summary of the passed in list of Target objects."""
# Create a list that is in order by time stamp and has entries for the
......@@ -273,7 +278,7 @@ def SummarizeEntries(entries):
weighted_time_by_ext = {}
# Scan through all of the targets to build up per-extension statistics.
for target in entries:
extension = GetExtension(target)
extension = GetExtension(target, extra_step_types)
time_by_ext[extension] = time_by_ext.get(extension, 0) + target.Duration()
weighted_time_by_ext[extension] = weighted_time_by_ext.get(extension,
0) + target.WeightedDuration()
......@@ -301,6 +306,10 @@ def main():
parser = argparse.ArgumentParser()
parser.add_argument('-C', dest='build_directory',
help='Build directory.')
parser.add_argument(
'-s',
'--step-types',
help='semicolon separated fnmatch patterns for build-step grouping')
parser.add_argument('--log-file',
help="specific ninja log file to analyze.")
args, _extra_args = parser.parse_known_args()
......@@ -308,11 +317,20 @@ def main():
log_file = os.path.join(args.build_directory, log_file)
if args.log_file:
log_file = args.log_file
if not args.step_types:
# Offer a convenient way to add extra step types automatically, including
# when this script is run by autoninja. get() returns None if the variable
# isn't set.
args.step_types = os.environ.get('chromium_step_types')
if args.step_types:
# Make room for the extra build types.
global long_ext_count
long_ext_count += len(args.step_types.split(';'))
try:
with open(log_file, 'r') as log:
entries = ReadTargets(log, False)
SummarizeEntries(entries)
SummarizeEntries(entries, args.step_types)
except IOError:
print('Log file %r not found, no build summary created.' % log_file)
return errno.ENOENT
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment