Skip to content

Commit ece2050

Browse files
committed
Use jemalloc as the global allocator
Using jemalloc provides a 20% max RSS reduction and 15% speed up in total indexing + resolution time
1 parent 558509e commit ece2050

4 files changed

Lines changed: 18 additions & 10 deletions

File tree

ext/rubydex/extconf.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
ENV["RUSTFLAGS"] = "-Zsanitizer=#{ENV["SANITIZER"]}"
7979
"cargo +nightly build -Zbuild-std #{cargo_args.join(" ")}".strip
8080
else
81-
"cargo build #{cargo_args.join(" ")}".strip
81+
"cargo build --features rubydex/jemalloc_dylib #{cargo_args.join(" ")}".strip
8282
end
8383

8484
lib_dir = gem_dir.join("lib").join("rubydex")

rust/rubydex/Cargo.toml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ path = "src/main.rs"
1919
crate-type = ["rlib"]
2020

2121
[features]
22+
jemalloc = ["dep:tikv-jemallocator"]
23+
# The Ruby native extension uses a dlopen to load the rubydex shared object. In these scenarios, jemalloc must be linked
24+
# dynamically or else the process crashes. This has a small performance cost, which we don't need to pay when using the
25+
# Rust crate by itself, so we gate it with a feature
26+
jemalloc_dylib = ["jemalloc", "tikv-jemallocator/disable_initial_exec_tls"]
2227
test_utils = ["dep:tempfile"]
2328

2429
[dependencies]
@@ -37,8 +42,11 @@ crossbeam-deque = "0.8"
3742
crossbeam-utils = "0.8"
3843
crossbeam-channel = "0.5"
3944

45+
[target.'cfg(not(target_os = "windows"))'.dependencies]
46+
tikv-jemallocator = { version = "0.7.0", optional = true }
47+
4048
[dev-dependencies]
41-
rubydex = { path = ".", features = ["test_utils"] }
49+
rubydex = { path = ".", features = ["test_utils", "jemalloc"] }
4250
tempfile = "3.0"
4351
assert_cmd = "2.0"
4452
predicates = "3.1"

rust/rubydex/benches/graph_memory.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
//! Jemalloc does not compile on Windows, so this memory benchmark executable is a no-op
2-
3-
#[cfg(not(target_os = "windows"))]
1+
#[cfg(all(feature = "jemalloc", not(target_os = "windows")))]
42
mod imp {
53
use std::collections::HashSet;
64

@@ -12,10 +10,6 @@ mod imp {
1210
};
1311
use tikv_jemalloc_ctl::{epoch, stats};
1412

15-
// Substitute the global allocator by jemalloc, so that we can track all allocations and measure the graph usage
16-
#[global_allocator]
17-
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
18-
1913
/// Advance the jemalloc epoch (stats are cached between epochs) and read the
2014
/// number of bytes currently allocated by the application.
2115
fn allocated_bytes() -> usize {
@@ -47,6 +41,6 @@ mod imp {
4741
}
4842

4943
fn main() {
50-
#[cfg(not(target_os = "windows"))]
44+
#[cfg(all(feature = "jemalloc", not(target_os = "windows")))]
5145
imp::run();
5246
}

rust/rubydex/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
// Setting the global allocator needs to happen during linking and consumers may not always want to change the global
2+
// allocator. We gate the usage of jemalloc with a cargo feature, so that consumers can decide if they want to use it
3+
#[cfg(all(feature = "jemalloc", not(target_os = "windows")))]
4+
#[global_allocator]
5+
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
6+
17
pub mod compile_assertions;
28
pub mod config;
39
pub mod diagnostic;

0 commit comments

Comments
 (0)