Skip to content

Commit c475294

Browse files
authored
feat: provide affordance for OCIImage actions to reserve more resources (#650)
1 parent 899af81 commit c475294

File tree

5 files changed

+113
-15
lines changed

5 files changed

+113
-15
lines changed

docs/image.md

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/big_image/BUILD.bazel

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
load("@rules_pkg//pkg:tar.bzl", "pkg_tar")
22
load("//oci:defs.bzl", "oci_image")
33

4-
54
# These numbers were gathered on a `Apple M2 Pro`
65
# Darwin Kernel Version 23.2.0: Wed Nov 15 21:55:06 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T6020
76
# 10 CPU x 32GB RAM
87

98
# 1- Create an image with 10 layers 3GiB each.
109
# Perf: `< 50s`
11-
N_BASE_LAYERS=10
10+
N_BASE_LAYERS = 10
1211

1312
genrule(
1413
name = "3gib_file",
15-
cmd = "mkfile 3G $@",
1614
outs = ["3gib_file.out"],
15+
cmd = "mkfile 3G $@",
1716
tags = ["manual"],
1817
)
1918

@@ -29,10 +28,10 @@ genrule(
2928

3029
oci_image(
3130
name = "base",
32-
os = "linux",
3331
architecture = "arm64",
34-
tars = [":blayer_%s" % i for i in range(N_BASE_LAYERS)],
32+
os = "linux",
3533
tags = ["manual"],
34+
tars = [":blayer_%s" % i for i in range(N_BASE_LAYERS)],
3635
)
3736

3837
# 2- Create an image that extends the base without adding additional layers
@@ -44,13 +43,11 @@ oci_image(
4443
tags = ["manual"],
4544
)
4645

47-
48-
4946
# 3- Create an image that extends the base with additional layers
5047
# Perf: `< 2s` if bazel doesn't permit tree artifact symlinks (for copying the base layers)
5148
# Perf: `< 0.5s` if bazel permits tree artifact symlinks (for linking the base layers)
5249
# Perf: `< 20s` for adding the new 5 layers, 3gib each.
53-
N_LAYERS=5
50+
N_LAYERS = 5
5451

5552
[
5653
pkg_tar(
@@ -61,11 +58,11 @@ N_LAYERS=5
6158
for i in range(N_LAYERS)
6259
]
6360

64-
6561
oci_image(
6662
name = "extended",
6763
base = ":base",
68-
tars = [":layer_%s" % i for i in range(N_LAYERS)],
64+
# Tell Bazel to reserve more than the default 250MB of RAM for the OCIImage action
65+
resource_set = "mem_8g",
6966
tags = ["manual"],
67+
tars = [":layer_%s" % i for i in range(N_LAYERS)],
7068
)
71-

oci/private/BUILD.bazel

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ bzl_library(
2727
"//docs:__pkg__",
2828
"//oci:__subpackages__",
2929
],
30-
deps = [":util"],
30+
deps = [
31+
":resource_sets",
32+
":util",
33+
],
3134
)
3235

3336
bzl_library(
@@ -108,3 +111,9 @@ bzl_library(
108111
"@bazel_skylib//lib:versions",
109112
],
110113
)
114+
115+
bzl_library(
116+
name = "resource_sets",
117+
srcs = ["resource_sets.bzl"],
118+
visibility = ["//oci:__subpackages__"],
119+
)

oci/private/image.bzl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"Implementation details for image rule"
22

3-
load("//oci/private:util.bzl", "util")
3+
load("resource_sets.bzl", "resource_set", "resource_set_attr")
4+
load("util.bzl", "util")
45

56
_DOC = """Build an OCI compatible container image.
67
@@ -189,6 +190,7 @@ def _oci_image_impl(ctx):
189190
tools = [crane.crane_info.binary, registry.registry_info.launcher, registry.registry_info.registry, jq.jqinfo.bin],
190191
mnemonic = "OCIImage",
191192
progress_message = "OCI Image %{label}",
193+
resource_set = resource_set(ctx.attr),
192194
)
193195

194196
return [
@@ -199,7 +201,7 @@ def _oci_image_impl(ctx):
199201

200202
oci_image = rule(
201203
implementation = _oci_image_impl,
202-
attrs = _attrs,
204+
attrs = dict(_attrs, **resource_set_attr),
203205
doc = _DOC,
204206
toolchains = [
205207
"@bazel_tools//tools/sh:toolchain_type",

oci/private/resource_sets.bzl

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
"""Utilities for rules that expose resource_set on ctx.actions.run[_shell]
2+
3+
Workaround for https://github.com/bazelbuild/bazel/issues/15187
4+
Vendored from https://github.com/aspect-build/bazel-lib/blob/cc956d8589c866339f81637037435366c25f582b/lib/resource_sets.bzl
5+
6+
Note, this workaround only provides some fixed values for either CPU or Memory.
7+
8+
Rule authors who are ALSO the BUILD author might know better, and can
9+
write custom resource_set functions for use within their own repository.
10+
This seems to be the use case that Google engineers imagined.
11+
"""
12+
13+
resource_set_values = [
14+
"cpu_2",
15+
"cpu_4",
16+
"default",
17+
"mem_512m",
18+
"mem_1g",
19+
"mem_2g",
20+
"mem_4g",
21+
"mem_8g",
22+
"mem_16g",
23+
"mem_32g",
24+
]
25+
26+
def _resource_set_cpu_2(_, __):
27+
return {"cpu": 2}
28+
29+
def _resource_set_cpu_4(_, __):
30+
return {"cpu": 4}
31+
32+
def _resource_set_mem_512m(_, __):
33+
return {"memory": 512}
34+
35+
def _resource_set_mem_1g(_, __):
36+
return {"memory": 1024}
37+
38+
def _resource_set_mem_2g(_, __):
39+
return {"memory": 2048}
40+
41+
def _resource_set_mem_4g(_, __):
42+
return {"memory": 4096}
43+
44+
def _resource_set_mem_8g(_, __):
45+
return {"memory": 8192}
46+
47+
def _resource_set_mem_16g(_, __):
48+
return {"memory": 16384}
49+
50+
def _resource_set_mem_32g(_, __):
51+
return {"memory": 32768}
52+
53+
# buildifier: disable=function-docstring
54+
def resource_set(attr):
55+
if attr.resource_set == "cpu_2":
56+
return _resource_set_cpu_2
57+
if attr.resource_set == "cpu_4":
58+
return _resource_set_cpu_4
59+
if attr.resource_set == "default":
60+
return None
61+
if attr.resource_set == "mem_512m":
62+
return _resource_set_mem_512m
63+
if attr.resource_set == "mem_1g":
64+
return _resource_set_mem_1g
65+
if attr.resource_set == "mem_2g":
66+
return _resource_set_mem_2g
67+
if attr.resource_set == "mem_4g":
68+
return _resource_set_mem_4g
69+
if attr.resource_set == "mem_8g":
70+
return _resource_set_mem_8g
71+
if attr.resource_set == "mem_16g":
72+
return _resource_set_mem_16g
73+
if attr.resource_set == "mem_32g":
74+
return _resource_set_mem_32g
75+
fail("unknown resource set", attr.resource_set)
76+
77+
resource_set_attr = {
78+
"resource_set": attr.string(
79+
doc = """A predefined function used as the resource_set for actions.
80+
81+
Used with --experimental_action_resource_set to reserve more RAM/CPU, preventing Bazel overscheduling resource-intensive actions.
82+
83+
By default, Bazel allocates 1 CPU and 250M of RAM.
84+
https://github.com/bazelbuild/bazel/blob/058f943037e21710837eda9ca2f85b5f8538c8c5/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java#L77
85+
""",
86+
default = "default",
87+
values = resource_set_values,
88+
),
89+
}

0 commit comments

Comments
 (0)