Skip to content

Commit a107240

Browse files
authored
[bazel] cross language LTO (#32368)
This PR enables cross language LTO for our release builds, meaning function calls from external C dependencies like `libdecimal` can potentially get inlined into Rust code. The way this works is when building our final binaries, e.g. `environmentd` and `clusterd`, we specify the `-Clinker-plugin-lto` flag to `rustc` which has our linker (`lld`) run the LTO passes instead of `rustc`. At which point all of our Rust and C code has been compiled to LLVM bitcode so to `lld` is free to optimize across languages. This only works when building for Linux. Arguments that `rustc` passes to the linker when targetting macOS don't seem to be supported by `ld64.lld`? See rust-lang/rust#60059 for some more investigation. ### Motivation Faster runtime performance. ### Tips for reviewer The commits are broken down as follows: 1. Some Bazel configuration so we can detect when the cross language LTO is requested _and_ when we're building on a Linux machine. 2. Updates to cargo-gazelle so we specify the right `rustc` flags. Theoretically something like this could be upstreamed into `rules_rust` which I started working on in bazelbuild/rules_rust#3162. But for now updating cargo-gazelle is a lot easier. 3. Running `bin/bazel gen` ### Checklist - [ ] This PR has adequate test coverage / QA involvement has been duly considered. ([trigger-ci for additional test/nightly runs](https://trigger-ci.dev.materialize.com/)) - [ ] This PR has an associated up-to-date [design doc](https://github.com/MaterializeInc/materialize/blob/main/doc/developer/design/README.md), is a design doc ([template](https://github.com/MaterializeInc/materialize/blob/main/doc/developer/design/00000000_template.md)), or is sufficiently small to not require a design. <!-- Reference the design in the description. --> - [ ] If this PR evolves [an existing `$T ⇔ Proto$T` mapping](https://github.com/MaterializeInc/materialize/blob/main/doc/developer/command-and-response-binary-encoding.md) (possibly in a backwards-incompatible way), then it is tagged with a `T-proto` label. - [ ] If this PR will require changes to cloud orchestration or tests, there is a companion cloud PR to account for those changes that is tagged with the release-blocker label ([example](MaterializeInc/cloud#5021)). <!-- Ask in #team-cloud on Slack if you need help preparing the cloud PR. --> - [ ] If this PR includes major [user-facing behavior changes](https://github.com/MaterializeInc/materialize/blob/main/doc/developer/guide-changes.md#what-changes-require-a-release-note), I have pinged the relevant PM to schedule a changelog post.
1 parent 26e5919 commit a107240

File tree

25 files changed

+140
-29
lines changed

25 files changed

+140
-29
lines changed

.bazelrc

+1
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ build:release --compilation_mode=opt
170170
build:release-lto --copt=-flto=thin
171171
build:release-lto --linkopt=-flto=thin
172172
build:release-lto --@rules_rust//rust/settings:lto=thin
173+
build:release-lto --@//misc/bazel/platforms:xlang_lto=True
173174

174175
# Builds from `main` or tagged builds.
175176
#

misc/bazel/cargo-gazelle/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ rust_binary(
9090
lint_config = ":lints",
9191
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
9292
rustc_env = {},
93-
rustc_flags = ["-Copt-level=3"],
93+
rustc_flags = ["-Copt-level=3"] + select({
94+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
95+
"//conditions:default": [],
96+
}),
9497
version = "0.0.0",
9598
deps = [":cargo_gazelle"] + all_crate_deps(normal = True),
9699
)

misc/bazel/cargo-gazelle/src/config.rs

+19
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::collections::BTreeMap;
1313
use guppy::graph::PackageMetadata;
1414
use std::sync::LazyLock;
1515

16+
use crate::ToBazelDefinition;
1617
use crate::targets::{AdditiveContent, RustTestSize};
1718

1819
const KEY_NAME: &str = "cargo-gazelle";
@@ -315,3 +316,21 @@ impl CommonConfig {
315316
&self.rustc_env
316317
}
317318
}
319+
320+
/// Values that are mirrored in `/misc/bazel/platforms/BUILD.bazel`.
321+
#[derive(Debug, Copy, Clone)]
322+
pub enum ConfigSettingGroup {
323+
XlangLtoEnabled,
324+
}
325+
326+
impl ToBazelDefinition for ConfigSettingGroup {
327+
fn format(&self, w: &mut dyn std::fmt::Write) -> Result<(), std::fmt::Error> {
328+
match self {
329+
ConfigSettingGroup::XlangLtoEnabled => {
330+
write!(w, "\"@//misc/bazel/platforms:xlang_lto_enabled\"")?
331+
}
332+
}
333+
334+
Ok(())
335+
}
336+
}

misc/bazel/cargo-gazelle/src/lib.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use std::collections::{BTreeMap, VecDeque};
1111
use std::fmt::{self, Debug, Write};
1212
use std::rc::Rc;
1313

14-
use crate::platforms::PlatformVariant;
1514
use crate::targets::RustTarget;
1615

1716
pub mod args;
@@ -510,20 +509,21 @@ impl ToBazelDefinition for Glob {
510509
/// ```
511510
#[derive(Debug)]
512511
pub struct Select<T> {
513-
entries: BTreeMap<PlatformVariant, T>,
512+
entries: BTreeMap<String, T>,
514513
default: T,
515514
}
516515

517516
impl<T> Select<T> {
518-
pub fn new<E, I>(entires: I, default: E) -> Select<T>
517+
pub fn new<E, I, J>(entires: I, default: E) -> Select<T>
519518
where
520519
E: Into<T>,
521-
I: IntoIterator<Item = (PlatformVariant, E)>,
520+
J: ToBazelDefinition,
521+
I: IntoIterator<Item = (J, E)>,
522522
{
523523
Select {
524524
entries: entires
525525
.into_iter()
526-
.map(|(variant, entry)| (variant, entry.into()))
526+
.map(|(variant, entry)| (variant.to_bazel_definition(), entry.into()))
527527
.collect(),
528528
default: default.into(),
529529
}
@@ -538,7 +538,7 @@ impl<T: ToBazelDefinition> ToBazelDefinition for Select<T> {
538538
{
539539
let mut w = w.indent();
540540
for (variant, entry) in &self.entries {
541-
variant.format(&mut w)?;
541+
write!(w, "{variant}")?;
542542
write!(w, ": ")?;
543543
entry.format(&mut w)?;
544544
writeln!(w, ",")?;

misc/bazel/cargo-gazelle/src/targets.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use std::collections::{BTreeMap, BTreeSet};
2121
use std::fmt::{self, Write};
2222
use std::str::FromStr;
2323

24-
use crate::config::{CrateConfig, GlobalConfig};
24+
use crate::config::{ConfigSettingGroup, CrateConfig, GlobalConfig};
2525
use crate::context::CrateContext;
2626
use crate::platforms::PlatformVariant;
2727
use crate::rules::Rule;
@@ -382,8 +382,17 @@ impl RustBinary {
382382
let (paths, globs) = bin_config.common().compile_data();
383383
let compile_data = List::new(paths).concat_other(globs.map(Glob::new));
384384

385+
let xlang_lto_select: Select<List<QuotedString>> = Select::new(
386+
[(
387+
ConfigSettingGroup::XlangLtoEnabled,
388+
vec![QuotedString::new("-Clinker-plugin-lto")],
389+
)],
390+
vec![],
391+
);
392+
385393
let env = Dict::new(bin_config.env());
386-
let rustc_flags = List::new(bin_config.common().rustc_flags());
394+
let rustc_flags =
395+
List::new(bin_config.common().rustc_flags()).concat_other(xlang_lto_select);
387396
let rustc_env = Dict::new(bin_config.common().rustc_env());
388397

389398
Ok(Some(RustBinary {

misc/bazel/platforms/BUILD.bazel

+23-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ support building Materialize for.
1616
"""
1717

1818
load("@bazel_skylib//lib:selects.bzl", "selects")
19-
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
19+
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "string_flag")
2020

2121
# A flag that we can specify on the command line to configure whether or not we
2222
# build with a sanitizer.
@@ -45,6 +45,28 @@ config_setting(
4545
flag_values = {":sanitizer": "hwaddress"},
4646
)
4747

48+
bool_flag(
49+
name = "xlang_lto",
50+
build_setting_default = False,
51+
)
52+
53+
config_setting(
54+
name = "use_xlang_lto",
55+
flag_values = {":xlang_lto": "True"},
56+
)
57+
58+
# With our current toolchain setup, cross language LTO is only supported when building for Linux.
59+
#
60+
# See <https://github.com/rust-lang/rust/issues/60059> for macOS support.
61+
selects.config_setting_group(
62+
name = "xlang_lto_enabled",
63+
match_all = [
64+
"@platforms//os:linux",
65+
":use_xlang_lto",
66+
],
67+
visibility = ["//visibility:public"],
68+
)
69+
4870
# We only want to use jemalloc if we're building for Linux and we're not using sanitizers.
4971
selects.config_setting_group(
5072
name = "use_jemalloc",

src/balancerd/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,10 @@ rust_binary(
179179
lint_config = ":lints",
180180
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
181181
rustc_env = {},
182-
rustc_flags = [],
182+
rustc_flags = [] + select({
183+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
184+
"//conditions:default": [],
185+
}),
183186
version = "0.144.0-dev.0",
184187
deps = [
185188
":mz_balancerd",

src/catalog-debug/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ rust_binary(
3030
lint_config = ":lints",
3131
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
3232
rustc_env = {},
33-
rustc_flags = [],
33+
rustc_flags = [] + select({
34+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
35+
"//conditions:default": [],
36+
}),
3437
version = "0.144.0-dev.0",
3538
deps = [
3639
"//src/adapter:mz_adapter",

src/clusterd/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,10 @@ rust_binary(
156156
lint_config = ":lints",
157157
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
158158
rustc_env = {},
159-
rustc_flags = [],
159+
rustc_flags = [] + select({
160+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
161+
"//conditions:default": [],
162+
}),
160163
version = "0.144.0-dev.0",
161164
deps = [
162165
":mz_clusterd",

src/environmentd/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,10 @@ rust_binary(
793793
lint_config = ":lints",
794794
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
795795
rustc_env = {},
796-
rustc_flags = [],
796+
rustc_flags = [] + select({
797+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
798+
"//conditions:default": [],
799+
}),
797800
version = "0.144.0-dev.0",
798801
deps = [
799802
":mz_environmentd",

src/fivetran-destination/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,10 @@ rust_binary(
116116
lint_config = ":lints",
117117
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
118118
rustc_env = {},
119-
rustc_flags = [],
119+
rustc_flags = [] + select({
120+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
121+
"//conditions:default": [],
122+
}),
120123
version = "0.0.0",
121124
deps = [
122125
":mz_fivetran_destination",

src/frontegg-mock/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,10 @@ rust_binary(
132132
lint_config = ":lints",
133133
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
134134
rustc_env = {},
135-
rustc_flags = [],
135+
rustc_flags = [] + select({
136+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
137+
"//conditions:default": [],
138+
}),
136139
version = "0.0.0",
137140
deps = [
138141
":mz_frontegg_mock",

src/interchange/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,10 @@ rust_binary(
126126
lint_config = ":lints",
127127
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
128128
rustc_env = {},
129-
rustc_flags = [],
129+
rustc_flags = [] + select({
130+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
131+
"//conditions:default": [],
132+
}),
130133
version = "0.0.0",
131134
deps = [
132135
":mz_interchange",

src/kafka-util/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,10 @@ rust_binary(
105105
lint_config = ":lints",
106106
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
107107
rustc_env = {},
108-
rustc_flags = [],
108+
rustc_flags = [] + select({
109+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
110+
"//conditions:default": [],
111+
}),
109112
version = "0.0.0",
110113
deps = [
111114
":mz_kafka_util",

src/lsp-server/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,10 @@ rust_binary(
144144
lint_config = ":lints",
145145
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
146146
rustc_env = {},
147-
rustc_flags = [],
147+
rustc_flags = [] + select({
148+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
149+
"//conditions:default": [],
150+
}),
148151
version = "0.3.0",
149152
deps = [
150153
":mz_lsp_server",

src/materialized/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ rust_binary(
3030
lint_config = ":lints",
3131
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
3232
rustc_env = {},
33-
rustc_flags = [],
33+
rustc_flags = [] + select({
34+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
35+
"//conditions:default": [],
36+
}),
3437
version = "0.144.0-dev.0",
3538
deps = [
3639
"//src/clusterd:mz_clusterd",

src/mz-debug/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ rust_binary(
3030
lint_config = ":lints",
3131
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
3232
rustc_env = {},
33-
rustc_flags = [],
33+
rustc_flags = [] + select({
34+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
35+
"//conditions:default": [],
36+
}),
3437
version = "0.1.0",
3538
deps = [
3639
"//src/build-info:mz_build_info",

src/mz/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ rust_binary(
139139
lint_config = ":lints",
140140
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
141141
rustc_env = {},
142-
rustc_flags = [],
142+
rustc_flags = [] + select({
143+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
144+
"//conditions:default": [],
145+
}),
143146
version = "0.3.0",
144147
deps = [
145148
":mz",

src/orchestratord/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,10 @@ rust_binary(
123123
lint_config = ":lints",
124124
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
125125
rustc_env = {},
126-
rustc_flags = [],
126+
rustc_flags = [] + select({
127+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
128+
"//conditions:default": [],
129+
}),
127130
version = "0.144.0-dev.0",
128131
deps = [
129132
":mz_orchestratord",

src/persist-cli/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ rust_binary(
3030
lint_config = ":lints",
3131
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
3232
rustc_env = {},
33-
rustc_flags = [],
33+
rustc_flags = [] + select({
34+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
35+
"//conditions:default": [],
36+
}),
3437
version = "0.0.0",
3538
deps = [
3639
"//src/http-util:mz_http_util",

src/pgtest/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ rust_binary(
9090
lint_config = ":lints",
9191
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
9292
rustc_env = {},
93-
rustc_flags = [],
93+
rustc_flags = [] + select({
94+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
95+
"//conditions:default": [],
96+
}),
9497
version = "0.0.0",
9598
deps = [
9699
":mz_pgtest",

src/s3-datagen/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ rust_binary(
3030
lint_config = ":lints",
3131
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
3232
rustc_env = {},
33-
rustc_flags = [],
33+
rustc_flags = [] + select({
34+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
35+
"//conditions:default": [],
36+
}),
3437
version = "0.0.0",
3538
deps = [
3639
"//src/aws-util:mz_aws_util",

src/sqllogictest/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,10 @@ rust_binary(
203203
lint_config = ":lints",
204204
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
205205
rustc_env = {},
206-
rustc_flags = [],
206+
rustc_flags = [] + select({
207+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
208+
"//conditions:default": [],
209+
}),
207210
version = "0.0.1",
208211
deps = [
209212
":mz_sqllogictest",

src/testdrive/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,10 @@ rust_binary(
165165
lint_config = ":lints",
166166
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
167167
rustc_env = {},
168-
rustc_flags = [],
168+
rustc_flags = [] + select({
169+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
170+
"//conditions:default": [],
171+
}),
169172
version = "0.144.0-dev.0",
170173
deps = [
171174
":mz_testdrive",

test/metabase/smoketest/BUILD.bazel

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ rust_binary(
3030
lint_config = ":lints",
3131
proc_macro_deps = [] + all_crate_deps(proc_macro = True),
3232
rustc_env = {},
33-
rustc_flags = [],
33+
rustc_flags = [] + select({
34+
"@//misc/bazel/platforms:xlang_lto_enabled": ["-Clinker-plugin-lto"],
35+
"//conditions:default": [],
36+
}),
3437
version = "0.0.0",
3538
deps = [
3639
"//src/metabase:mz_metabase",

0 commit comments

Comments
 (0)