runsc: Do not precompile seccomp-bpf filters in fastbuild mode.

While precompilation is pretty fast, its presence in the build graph
removes concurrency from the `runsc` build process. This is because the
precompilation generation binary is dependency-heavy (e.g. it needs all
platform implementations), yet must be built before the `//runsc/boot/filter`
package is built, thus slowing down the `runsc` build process.

This change creates a low-dependency "stubbed" version of this generation
binary when running in `fastbuild` mode. The generated code in this mode
contains no precompiled seccomp programs; they are instead all built from
scratch on container startup. This trades off build speed vs container
startup speed.

PiperOrigin-RevId: 586520033
This commit is contained in:
Etienne Perot
2023-11-29 19:45:20 -08:00
committed by gVisor bot
parent 4b925cc1cd
commit c11e182262
3 changed files with 104 additions and 33 deletions
+91 -28
View File
@@ -7,7 +7,8 @@ def precompiled_seccomp_rules(
programs_to_compile_go_library,
programs_to_compile_go_import,
out,
out_package_name):
out_package_name,
exclude_in_fastbuild = False):
"""Generates a Go source file containing precompiled seccomp-bpf programs.
Args:
@@ -24,7 +25,16 @@ def precompiled_seccomp_rules(
function:
GetPrecompiled(programName string) (precompiledseccomp.Program, bool)
out_package_name: Go package name that `out` belongs to.
exclude_in_fastbuild: Whether to skip precompilation in fastbuild mode.
The auto-generated `GetPrecompiled` function will fail all lookups.
"""
if exclude_in_fastbuild:
native.config_setting(
name = name + "_fastbuild_cond",
values = {
"compilation_mode": "fastbuild",
},
)
# This genrule copies precompiled_lib.tmpl.go to the directory of wherever
# `precompiled_seccomp_rules` is called.
@@ -41,49 +51,102 @@ def precompiled_seccomp_rules(
# This genrule generates the Go file of the binary that, when run,
# precompiles rules and writes them to a designated file.
gen_cmd_template = (
" while IFS= read -r line; do" +
" if echo \"$$line\" | grep -q 'REPLACED_IMPORT_THIS_IS_A_LOAD_BEARING_COMMENT'; then" +
" {rules_import_echo}" +
" elif echo \"$$line\" | grep -q 'PROGRAMS_FUNC_THIS_IS_A_LOAD_BEARING_COMMENT'; then" +
" {load_programs_fn_echo}" +
" elif echo \"$$line\" | grep -q 'go:embed precompiled_lib.tmpl.go'; then" +
" echo -e \"//go:embed " + out + ".gen.lib.tmpl.go\";" +
" else" +
" echo \"$$line\";" +
" fi;" +
" done" +
" < $(SRCS)" +
" > $@"
)
gen_cmd = gen_cmd_template.format(
rules_import_echo = (
"echo -e \"\\\\trules \\\"" +
programs_to_compile_go_import +
"\\\"\";"
),
load_programs_fn_echo = (
"echo -e \"var loadProgramsFn = rules.PrecompiledPrograms\";"
),
)
native.genrule(
name = name + "_gen",
outs = [out + ".gen.go"],
cmd = (
" while IFS= read -r line; do" +
" if echo \"$$line\" | grep -q 'REPLACED_IMPORT_THIS_IS_A_LOAD_BEARING_COMMENT'; then" +
" echo -e \"\\\\trules \\\"" + programs_to_compile_go_import + "\\\"\";" +
" elif echo \"$$line\" | grep -q 'PROGRAMS_FUNC_THIS_IS_A_LOAD_BEARING_COMMENT'; then" +
" echo -e \"var loadProgramsFn = rules.PrecompiledPrograms\";" +
" elif echo \"$$line\" | grep -q 'go:embed precompiled_lib.tmpl.go'; then" +
" echo -e \"//go:embed " + out + ".gen.lib.tmpl.go\";" +
" else" +
" echo \"$$line\";" +
" fi;" +
" done" +
" < $(SRCS)" +
" > $@"
),
cmd = gen_cmd,
srcs = [
"//pkg/seccomp/precompiledseccomp:precompile_gen.go",
],
)
if exclude_in_fastbuild:
native.genrule(
name = name + "_gen_stubbed",
outs = [out + ".gen_stubbed.go"],
cmd = gen_cmd_template.format(
rules_import_echo = "true;",
load_programs_fn_echo = (
"echo -e \"var loadProgramsFn func() ([]precompiledseccomp.Program, error) = nil\";"
),
),
srcs = [
"//pkg/seccomp/precompiledseccomp:precompile_gen.go",
],
)
# This defines the go_binary for the Go file we just generated.
base_gen_bin_deps = [
"//pkg/seccomp/precompiledseccomp",
"//runsc/flag",
]
gen_bin_deps = [programs_to_compile_go_library] + base_gen_bin_deps
go_binary(
name = name + "_gen_bin",
srcs = [out + ".gen.go"],
deps = [
programs_to_compile_go_library,
"//runsc/flag",
],
deps = gen_bin_deps,
embedsrcs = [
":" + out + ".gen.lib.tmpl.go",
],
)
if exclude_in_fastbuild:
go_binary(
name = name + "_gen_stubbed_bin",
srcs = [out + ".gen_stubbed.go"],
deps = base_gen_bin_deps,
embedsrcs = [
":" + out + ".gen.lib.tmpl.go",
],
)
# This genrule actually runs the go_binary we just declared, and writes
# its output (containing the precompiled rules) to the desired `out` file.
native.genrule(
name = name,
outs = [out],
cmd = (
"$(location :" + name + "_gen_bin) --package='" + out_package_name + "' --out=$@"
),
tools = [":" + name + "_gen_bin"],
)
out_cmd = "$(location :" + name + "_gen_bin) --package='" + out_package_name + "' --out=$@"
if exclude_in_fastbuild:
native.genrule(
name = name,
outs = [out],
cmd = select({
":" + name + "_fastbuild_cond": (
"$(location :" + name + "_gen_stubbed_bin) --package='" + out_package_name + "' --out=$@"
),
"//conditions:default": out_cmd,
}),
tools = select({
":" + name + "_fastbuild_cond": [":" + name + "_gen_stubbed_bin"],
"//conditions:default": [":" + name + "_gen_bin"],
}),
)
else:
native.genrule(
name = name,
outs = [out],
cmd = (
"$(location :" + name + "_gen_bin) --package='" + out_package_name + "' --out=$@"
),
tools = [":" + name + "_gen_bin"],
)
@@ -23,9 +23,11 @@ import (
"sort"
"strings"
"gvisor.dev/gvisor/pkg/seccomp/precompiledseccomp"
"gvisor.dev/gvisor/runsc/flag"
// This import will be replaced by the one specified in the genrule.
// This import will be replaced by the one specified in the genrule,
// or removed if stubbed out in fastbuild mode.
"gvisor.dev/gvisor/pkg/seccomp/precompiledseccomp/example" // REPLACED_IMPORT_THIS_IS_A_LOAD_BEARING_COMMENT
)
@@ -47,16 +49,21 @@ var (
)
// loadProgramsFn loads seccomp programs to be precompiled.
// It may be nil when it is stubbed out in fastbuild mode.
var loadProgramsFn = example.PrecompiledPrograms // PROGRAMS_FUNC_THIS_IS_A_LOAD_BEARING_COMMENT
func main() {
flag.Parse()
// Get a sorted list of programs.
programs, err := loadProgramsFn()
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot get list of programs to precompile: %v\n", err)
os.Exit(1)
var programs []precompiledseccomp.Program
if loadProgramsFn != nil {
var err error
programs, err = loadProgramsFn()
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot get list of programs to precompile: %v\n", err)
os.Exit(1)
}
}
programNames := make(map[string]struct{}, len(programs))
for _, program := range programs {
+1
View File
@@ -10,6 +10,7 @@ package(
precompiled_seccomp_rules(
name = "filter_precompiled",
out = "filter_precompiled.go",
exclude_in_fastbuild = True,
out_package_name = "filter",
programs_to_compile_go_import = "gvisor.dev/gvisor/runsc/boot/filter/config",
programs_to_compile_go_library = "//runsc/boot/filter/config",