Skip to content

Commit a78505e

Browse files
committed
tcmalloc rust bindings
1 parent e5bdfaf commit a78505e

File tree

8 files changed

+439
-6
lines changed

8 files changed

+439
-6
lines changed

BUILD

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,41 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
15+
load("@bazel_skylib//rules:native_binary.bzl", "native_binary")
16+
load("@rules_cc//cc:defs.bzl", "cc_import")
17+
load("@rules_rust_bindgen//:defs.bzl", "rust_bindgen_toolchain")
18+
19+
native_binary(
20+
name = "clang",
21+
src = "@llvm_toolchain_llvm//:bin/clang",
22+
visibility = ["//tcmalloc_rs:__subpackages__"],
23+
)
24+
25+
cc_import(
26+
name = "libclang",
27+
shared_library = "@llvm_toolchain_llvm//:libclang",
28+
visibility = ["//tcmalloc_rs:__subpackages__"],
29+
)
30+
31+
cc_import(
32+
name = "libstdcxx",
33+
static_library = "@llvm_toolchain_llvm//:lib/x86_64-unknown-linux-gnu/libc++.a",
34+
visibility = ["//tcmalloc_rs:__subpackages__"],
35+
)
36+
37+
rust_bindgen_toolchain(
38+
name = "rust_bindgen_toolchain",
39+
bindgen = "@rules_rust_bindgen//3rdparty:bindgen",
40+
clang = ":clang",
41+
libclang = ":libclang",
42+
libstdcxx = ":libstdcxx",
43+
visibility = ["//tcmalloc_rs:__subpackages__"],
44+
)
45+
46+
toolchain(
47+
name = "default_bindgen_toolchain",
48+
toolchain = ":rust_bindgen_toolchain",
49+
toolchain_type = "@rules_rust_bindgen//:toolchain_type",
50+
visibility = ["//tcmalloc_rs:__subpackages__"],
51+
)

MODULE.bazel

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,39 @@ bazel_dep(name = "protobuf", version = "27.5", repo_name = "com_google_protobuf"
2828
bazel_dep(name = "re2", version = "2024-02-01", repo_name = "com_googlesource_code_re2")
2929
bazel_dep(name = "rules_cc", version = "0.0.9")
3030
bazel_dep(name = "rules_fuzzing", version = "0.5.2")
31+
bazel_dep(name = "toolchains_llvm", version = "1.3.0")
32+
33+
bazel_dep(name = "rules_rust", version = "0.59.2")
34+
bazel_dep(name = "rules_rust_bindgen", version = "0.59.2")
35+
36+
37+
# Configure and register the toolchain.
38+
# https://github.com/bazel-contrib/toolchains_llvm/blob/master/toolchain/internal/llvm_distributions.bzl
39+
llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm", dev_dependency = True)
40+
41+
# LLVM toolchain.
42+
llvm.toolchain(
43+
name = "llvm_toolchain",
44+
llvm_version = "17.0.6",
45+
cxx_standard = {"": "c++19"},
46+
)
47+
use_repo(llvm, "llvm_toolchain", "llvm_toolchain_llvm")
48+
49+
rust = use_extension("@rules_rust//rust:extensions.bzl", "rust", dev_dependency = True)
50+
rust.toolchain(
51+
edition = "2021",
52+
versions = [
53+
"1.85.0",
54+
],
55+
)
56+
use_repo(rust, "rust_toolchains")
57+
58+
register_toolchains(
59+
"@rust_toolchains//:all",
60+
dev_dependency = True,
61+
)
62+
register_toolchains(
63+
"//:default_bindgen_toolchain",
64+
dev_dependency = True,
65+
)
66+

docs/quickstart.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,42 @@ build --cxxopt='-std=c++17'
254254

255255
Congratulations! You've created your first binary using TCMalloc.
256256

257+
## TCMalloc-rs
258+
This is the rust wrapper for using `TCMalloc` as a global allocator.
259+
### Building
260+
To build the `tcmalloc` rust bindings, you need to turn off the `alwayslink` flag on `cc_library` targets.
261+
This is done with the `--//tcmalloc:alwayslink=false` flag.
262+
263+
`//tcmalloc:tcmalloc` with `alwayslink=1` will produce `libtcmalloc.lo` which rustc does not recognize as a valid static library ([related](https://github.com/bazelbuild/rules_rust/issues/325#issuecomment-706548453)).
264+
Optionally turning off `alwayslink` for `tcmalloc_sys` will allow `bindgen` to successfully build.
265+
266+
#### Pagesize
267+
By default, `tcmalloc` build with support for `8k` pagesize.
268+
269+
To build `tcmalloc` with `32k` pagesizes, build `tcmalloc_rs` with `--//tcmalloc_rs:pagesize=32k`
270+
271+
To build `tcmalloc` with `512k` pagesizes, build `tcmalloc_rs` with `--//tcmalloc_rs:pagesize=512k`
272+
### Running Tests
273+
`bazel run //tcmalloc_rs:test --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux --//tcmalloc:alwayslink=false`
274+
275+
### Usage
276+
Add the bazel dependency:
277+
```Starlark
278+
//tcmalloc_rs
279+
```
280+
To use the allocator, add the following to your code:
281+
```rust
282+
// To set TCMalloc as the global allocator add this to your project:
283+
use tcmalloc_rs;
284+
285+
#[global_allocator]
286+
static GLOBAL: tcmalloc_rs::TCMalloc = tcmalloc_rs::TCMalloc;
287+
```
288+
289+
#### Running the example
290+
Take a look at the code in `tcmalloc_rs/main.rs` and run
291+
`bazel run //tcmalloc_rs:main --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux --//tcmalloc:alwayslink=false`.
292+
257293
## What's Next
258294

259295
* Read our [overview](overview.md), if you haven't already. The overview

tcmalloc/BUILD

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,28 @@
1818
# https://github.com/google/tcmalloc/tree/master/docs/design.md for a high-level description of
1919
# how this malloc works.
2020

21+
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
2122
load("//tcmalloc:copts.bzl", "TCMALLOC_DEFAULT_COPTS")
2223
load("//tcmalloc:variants.bzl", "create_tcmalloc_benchmark", "create_tcmalloc_libraries", "create_tcmalloc_testsuite")
2324

2425
package(default_visibility = ["//visibility:private"])
2526

2627
licenses(["notice"])
2728

28-
exports_files(["LICENSE"])
29+
exports_files(["LICENSE", "tcmalloc.h"])
30+
31+
bool_flag(
32+
name = "alwayslink",
33+
build_setting_default = True,
34+
)
35+
36+
config_setting(
37+
name = "unlinked",
38+
flag_values = {
39+
":alwayslink": "false",
40+
},
41+
visibility = ["//visibility:public"],
42+
)
2943

3044
config_setting(
3145
name = "llvm",
@@ -108,7 +122,10 @@ cc_library(
108122
"@com_google_absl//absl/time",
109123
"@com_google_absl//absl/types:span",
110124
],
111-
alwayslink = 1,
125+
alwayslink = select({
126+
":unlinked": 0,
127+
"//conditions:default": 1,
128+
}),
112129
)
113130

114131
cc_library(
@@ -334,7 +351,10 @@ create_tcmalloc_libraries(
334351
"@com_google_absl//absl/types:optional",
335352
"@com_google_absl//absl/types:span",
336353
],
337-
alwayslink = 1,
354+
alwayslink = select({
355+
":unlinked": 0,
356+
"//conditions:default": 1,
357+
}),
338358
)
339359

340360
# TEMPORARY. WILL BE REMOVED.
@@ -435,7 +455,10 @@ cc_library(
435455
"@com_google_absl//absl/time",
436456
"@com_google_absl//absl/types:span",
437457
],
438-
alwayslink = 1,
458+
alwayslink = select({
459+
":unlinked": 0,
460+
"//conditions:default": 1,
461+
}),
439462
)
440463

441464
# TCMalloc with 256k pages is usually faster but fragmentation is higher. See
@@ -458,7 +481,10 @@ cc_library(
458481
"@com_google_absl//absl/time",
459482
"@com_google_absl//absl/types:span",
460483
],
461-
alwayslink = 1,
484+
alwayslink = select({
485+
":unlinked": 0,
486+
"//conditions:default": 1,
487+
}),
462488
)
463489

464490
cc_library(

tcmalloc/selsan/BUILD

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ cc_library(
3838
"//tcmalloc/internal:logging",
3939
"@com_google_absl//absl/base:core_headers",
4040
],
41-
alwayslink = 1,
41+
alwayslink = select({
42+
"//tcmalloc:unlinked": 0,
43+
"//conditions:default": 1,
44+
}),
4245
)
4346

4447
cc_test(

tcmalloc_rs/BUILD

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
2+
load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library", "rust_test")
3+
load("@rules_rust_bindgen//:defs.bzl", "rust_bindgen_library")
4+
5+
string_flag(
6+
name = "pagesize",
7+
build_setting_default = "8k",
8+
)
9+
10+
config_setting(
11+
name = "large",
12+
flag_values = {
13+
":pagesize": "32k",
14+
},
15+
visibility = ["//visibility:public"],
16+
)
17+
18+
config_setting(
19+
name = "xlarge",
20+
flag_values = {
21+
":pagesize": "256k",
22+
},
23+
visibility = ["//visibility:public"],
24+
)
25+
26+
rust_bindgen_library(
27+
name = "tcmalloc_sys",
28+
cc_lib = select({
29+
":xlarge": "//tcmalloc:tcmalloc_256k_pages",
30+
":large": "//tcmalloc:tcmalloc_large_pages",
31+
"//conditions:default": "//tcmalloc",
32+
}),
33+
header = "//tcmalloc:tcmalloc.h",
34+
clang_flags = [
35+
# "-v", # enable for debugging
36+
"-x",
37+
"c++",
38+
"-std=c++17",
39+
],
40+
bindgen_flags = [
41+
"--allowlist-function=TCMallocInternalMalloc",
42+
"--allowlist-function=TCMallocInternalFree",
43+
"--allowlist-function=TCMallocInternalCalloc",
44+
"--allowlist-function=TCMallocInternalRealloc",
45+
"--allowlist-function=malloc_usable_size",
46+
"--use-core", # don't compile with std, allows baremetal envs
47+
],
48+
rustc_flags = [
49+
"-Ccodegen-units=1",
50+
"-Copt-level=3",
51+
"-Cstrip=symbols",
52+
],
53+
)
54+
55+
rust_library(
56+
name = "tcmalloc_rs",
57+
deps = [":tcmalloc_sys"],
58+
srcs = ["lib.rs"],
59+
visibility = ["//visibility:public"],
60+
)
61+
62+
63+
# bazel test //tcmalloc_rs/... --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux --//tcmalloc:alwayslink=false
64+
rust_test(
65+
name = "test",
66+
size = "small",
67+
crate = ":tcmalloc_rs",
68+
)
69+
70+
# bazel run //tcmalloc_rs:main --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux --//tcmalloc:alwayslink=false
71+
rust_binary(
72+
name = "main",
73+
srcs = ["main.rs"],
74+
deps = [":tcmalloc_rs"],
75+
)

0 commit comments

Comments
 (0)