Skip to content

Commit

Permalink
build: emit performance JSON file for each ng_module() (#41125)
Browse files Browse the repository at this point in the history
A previous commit implemented a streamlined performance metric reporting
system for the compiler-cli, controlled via the compiler option
`tracePerformance`.

This commit adds a custom Bazel flag rule //packages/compiler-cli:ng_perf
to the repository, and wires it through to the `ng_module` implementation
such that if the flag is set, `ng_module` will produce perf results as part
of the build. The underlying mechanism of `//:ng_perf` is not exported from
`@angular/bazel` as a public rule that consumers can use, so there is little
risk of accidental dependency on the contents of these perf traces.

An alias is added so that `--ng_perf` is a Bazel flag which works in our
repository.

PR Close #41125
  • Loading branch information
alxhub committed Mar 24, 2021
1 parent 48fec08 commit b61c009
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 3 deletions.
7 changes: 7 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ build:remote --remote_executor=remotebuildexecution.googleapis.com
# retry mechanism and we do not want to retry unnecessarily if Karma already tried multiple times.
test:saucelabs --flaky_test_attempts=1

################
# Flag Aliases #
################

# --ng_perf will ask the Ivy compiler to produce performance results for each build.
build --flag_alias=ng_perf=//packages/compiler-cli:ng_perf

####################################################
# User bazel configuration
# NOTE: This needs to be the *last* entry in the config.
Expand Down
1 change: 1 addition & 0 deletions packages/bazel/index.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ load("//packages/bazel/src:ng_module.bzl", _ng_module = "ng_module_macro")

ng_module = _ng_module
ng_package = _ng_package

# DO NOT ADD PUBLIC API without including in the documentation generation
# Run `yarn bazel build //packages/bazel/docs` to verify
47 changes: 44 additions & 3 deletions packages/bazel/src/ng_module.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,19 @@ load(
"tsc_wrapped_tsconfig",
)

# enable_perf_logging controls whether Ivy's performance tracing system will be enabled for any
# compilation which includes this provider.
NgPerfInfo = provider(fields = ["enable_perf_logging"])

_FLAT_DTS_FILE_SUFFIX = ".bundle.d.ts"
_R3_SYMBOLS_DTS_FILE = "src/r3_symbols.d.ts"

def is_perf_requested(ctx):
enable_perf_logging = ctx.attr.perf_flag != None and ctx.attr.perf_flag[NgPerfInfo].enable_perf_logging == True
if enable_perf_logging and not is_ivy_enabled(ctx):
fail("Angular View Engine does not support performance tracing")
return enable_perf_logging

def is_ivy_enabled(ctx):
"""Determine if the ivy compiler should be used to by the ng_module.
Expand Down Expand Up @@ -278,6 +288,15 @@ def _expected_outs(ctx):
else:
i18n_messages_files = []

dev_perf_files = []
prod_perf_files = []

# In Ivy mode, dev and prod builds both produce a .json output containing performance metrics
# from the compiler for that build.
if is_perf_requested(ctx):
dev_perf_files = [ctx.actions.declare_file(ctx.label.name + "_perf_dev.json")]
prod_perf_files = [ctx.actions.declare_file(ctx.label.name + "_perf_prod.json")]

return struct(
closure_js = closure_js_files,
devmode_js = devmode_js_files,
Expand All @@ -288,6 +307,8 @@ def _expected_outs(ctx):
dts_bundles = dts_bundles,
bundle_index_typings = bundle_index_typings,
i18n_messages = i18n_messages_files,
dev_perf_files = dev_perf_files,
prod_perf_files = prod_perf_files,
)

# Determines if we need to generate View Engine shims (.ngfactory and .ngsummary files)
Expand Down Expand Up @@ -336,6 +357,15 @@ def _ngc_tsconfig(ctx, files, srcs, **kwargs):
"_useManifestPathsAsModuleName": (not _is_bazel()),
}

if is_perf_requested(ctx):
# In Ivy mode, set the `tracePerformance` Angular compiler option to enable performance
# metric output.
if "devmode_manifest" in kwargs:
perf_path = outs.dev_perf_files[0].path
else:
perf_path = outs.prod_perf_files[0].path
angular_compiler_options["tracePerformance"] = perf_path

if _should_produce_flat_module_outs(ctx):
angular_compiler_options["flatModuleId"] = ctx.attr.module_name
angular_compiler_options["flatModuleOutFile"] = _flat_module_out_file(ctx)
Expand Down Expand Up @@ -519,6 +549,7 @@ def _compile_action(
outputs,
dts_bundles_out,
messages_out,
perf_out,
tsconfig_file,
node_opts,
compile_mode):
Expand Down Expand Up @@ -563,12 +594,12 @@ def _compile_action(

def _prodmode_compile_action(ctx, inputs, outputs, tsconfig_file, node_opts):
outs = _expected_outs(ctx)
return _compile_action(ctx, inputs, outputs + outs.closure_js, None, outs.i18n_messages, tsconfig_file, node_opts, "prodmode")
return _compile_action(ctx, inputs, outputs + outs.closure_js + outs.prod_perf_files, None, outs.i18n_messages, outs.prod_perf_files, tsconfig_file, node_opts, "prodmode")

def _devmode_compile_action(ctx, inputs, outputs, tsconfig_file, node_opts):
outs = _expected_outs(ctx)
compile_action_outputs = outputs + outs.devmode_js + outs.declarations + outs.summaries + outs.metadata
_compile_action(ctx, inputs, compile_action_outputs, outs.dts_bundles, None, tsconfig_file, node_opts, "devmode")
compile_action_outputs = outputs + outs.devmode_js + outs.declarations + outs.summaries + outs.metadata + outs.dev_perf_files
_compile_action(ctx, inputs, compile_action_outputs, outs.dts_bundles, None, outs.dev_perf_files, tsconfig_file, node_opts, "devmode")

def _ts_expected_outs(ctx, label, srcs_files = []):
# rules_typescript expects a function with two or more arguments, but our
Expand Down Expand Up @@ -711,6 +742,16 @@ NG_MODULE_ATTRIBUTES = {
executable = True,
cfg = "host",
),
# In the angular/angular monorepo, //tools:defaults.bzl wraps the ng_module rule in a macro
# which sets this attribute to the //packages/compiler-cli:ng_perf flag.
# This is done to avoid exposing the flag to user projects, which would require:
# * defining the flag within @angular/bazel and referencing it correctly here, and
# * committing to the flag and its semantics (including the format of perf JSON files)
# as something users can depend upon.
"perf_flag": attr.label(
providers = [NgPerfInfo],
doc = "Private API to control production of performance metric JSON files",
),
"_supports_workers": attr.bool(default = True),
}

Expand Down
20 changes: 20 additions & 0 deletions packages/bazel/src/ng_perf.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright Google LLC All Rights Reserved.
#
# Use of this source code is governed by an MIT-style license that can be
# found in the LICENSE file at https://angular.io/license

load(":ng_module.bzl", "NgPerfInfo")

def _ng_perf_flag_impl(ctx):
return NgPerfInfo(enable_perf_logging = ctx.build_setting_value)

# `ng_perf_flag` is a special `build_setting` rule which ultimately enables a command-line boolean
# flag to control whether the `ng_module` rule produces performance tracing JSON files (in Ivy mode)
# as declared outputs.
#
# It does this via the `NgPerfInfo` provider and the `perf_flag` attriubute on `ng_module`. For more
# details, see: https://docs.bazel.build/versions/master/skylark/config.html
ng_perf_flag = rule(
implementation = _ng_perf_flag_impl,
build_setting = config.bool(flag = True),
)
10 changes: 10 additions & 0 deletions packages/compiler-cli/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package(default_visibility = ["//visibility:public"])

load("//tools:defaults.bzl", "pkg_npm", "ts_api_guardian_test", "ts_config", "ts_library")

# Load ng_perf_flag explicitly from ng_perf.bzl as it's private API, and not exposed to other
# consumers of @angular/bazel.
load("//packages/bazel/src:ng_perf.bzl", "ng_perf_flag")

ts_config(
name = "tsconfig",
src = "tsconfig-build.json",
Expand Down Expand Up @@ -88,3 +92,9 @@ ts_api_guardian_test(
],
golden = "angular/goldens/public-api/compiler-cli/compiler_options.d.ts",
)

# Controls whether the Ivy compiler produces performance traces as part of each build
ng_perf_flag(
name = "ng_perf",
build_setting_default = False,
)
1 change: 1 addition & 0 deletions tools/defaults.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ def ng_module(name, tsconfig = None, entry_point = None, testonly = False, deps
api_extractor = _INTERNAL_NG_MODULE_API_EXTRACTOR,
ng_xi18n = _INTERNAL_NG_MODULE_XI18N,
module_name = module_name,
perf_flag = "//packages/compiler-cli:ng_perf",
**kwargs
)

Expand Down

0 comments on commit b61c009

Please sign in to comment.