Skip to content

Commit

Permalink
Merge d7737fb into 9e5f77b
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra committed Dec 1, 2022
2 parents 9e5f77b + d7737fb commit 804a428
Show file tree
Hide file tree
Showing 9 changed files with 228 additions and 37 deletions.
9 changes: 5 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions crates/next-dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ name = "mod"
harness = false

[features]
default = ["cli"]
default = ["cli", "custom_allocator"]
cli = []
serializable = []
tokio_console = [
Expand All @@ -28,6 +28,7 @@ tokio_console = [
"turbo-tasks/tokio_tracing",
]
profile = []
custom_allocator = ["turbo-malloc/custom_allocator"]

[dependencies]
anyhow = "1.0.47"
Expand All @@ -41,7 +42,7 @@ portpicker = "0.1.1"
serde = "1.0.136"
serde_json = "1.0.85"
tokio = { version = "1.21.2", features = ["full"] }
turbo-malloc = { path = "../turbo-malloc" }
turbo-malloc = { path = "../turbo-malloc", default-features = false }
turbo-tasks = { path = "../turbo-tasks" }
turbo-tasks-fs = { path = "../turbo-tasks-fs" }
turbo-tasks-memory = { path = "../turbo-tasks-memory" }
Expand Down
47 changes: 34 additions & 13 deletions crates/next-dev/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ use next_core::{
next_image::NextImageContentSourceVc, source_map::NextSourceMapTraceContentSourceVc,
};
use owo_colors::OwoColorize;
use turbo_malloc::TurboMalloc;
use turbo_tasks::{
primitives::StringsVc, util::FormatDuration, RawVc, StatsType, TransientInstance,
TransientValue, TurboTasks, TurboTasksBackendApi, Value,
primitives::StringsVc,
util::{FormatBytes, FormatDuration},
RawVc, StatsType, TransientInstance, TransientValue, TurboTasks, TurboTasksBackendApi, Value,
};
use turbo_tasks_fs::{DiskFileSystemVc, FileSystemVc};
use turbo_tasks_memory::MemoryBackend;
Expand Down Expand Up @@ -448,24 +450,43 @@ pub async fn start_server(options: &DevServerOptions) -> Result<()> {
}

let stats_future = async move {
println!(
"{event_type} - initial compilation {start}",
event_type = "event".purple(),
start = FormatDuration(start.elapsed()),
);
if options.log_detail {
println!(
"{event_type} - initial compilation {start} ({memory})",
event_type = "event".purple(),
start = FormatDuration(start.elapsed()),
memory = FormatBytes(TurboMalloc::memory_usage())
);
} else {
println!(
"{event_type} - initial compilation {start}",
event_type = "event".purple(),
start = FormatDuration(start.elapsed()),
);
}

loop {
let update_future = profile_timeout(
tt_clone.as_ref(),
tt_clone.get_or_wait_update_info(Duration::from_millis(100)),
);

let (elapsed, _count) = update_future.await;
println!(
"{event_type} - updated in {elapsed}",
event_type = "event".purple(),
elapsed = FormatDuration(elapsed),
);
let (elapsed, count) = update_future.await;
if options.log_detail {
println!(
"{event_type} - updated in {elapsed} ({tasks} tasks, {memory})",
event_type = "event".purple(),
elapsed = FormatDuration(elapsed),
tasks = count,
memory = FormatBytes(TurboMalloc::memory_usage())
);
} else {
println!(
"{event_type} - updated in {elapsed}",
event_type = "event".purple(),
elapsed = FormatDuration(elapsed),
);
}
}
};

Expand Down
18 changes: 16 additions & 2 deletions crates/next-dev/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,23 @@ fn main() -> Result<()> {
unimplemented!("Cannot run binary without CLI feature enabled");
}

#[tokio::main]
#[cfg(feature = "cli")]
async fn main() -> Result<()> {
fn main() {
use turbo_malloc::TurboMalloc;

tokio::runtime::Builder::new_multi_thread()
.enable_all()
.on_thread_stop(|| {
TurboMalloc::thread_stop();
})
.build()
.unwrap()
.block_on(main_inner())
.unwrap()
}

#[cfg(feature = "cli")]
async fn main_inner() -> Result<()> {
let options = next_dev::devserver_options::DevServerOptions::parse();

if options.display_version {
Expand Down
7 changes: 4 additions & 3 deletions crates/node-file-trace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ path = "src/main.rs"
bench = false

[features]
default = ["cli"]
cli = ["dep:clap", "dep:turbo-malloc"]
default = ["cli", "custom_allocator"]
cli = ["dep:clap", "turbo-malloc"]
persistent_cache = [
# "dep:turbo-tasks-rocksdb"
]
Expand All @@ -22,11 +22,12 @@ tokio_console = [
"turbo-tasks/tokio_tracing",
]
node-api = []
custom_allocator = ["turbo-malloc", "turbo-malloc/custom_allocator"]

[dependencies]
clap = { version = "4.0.18", optional = true, features = ["derive"] }
owo-colors = "3"
turbo-malloc = { path = "../turbo-malloc", optional = true }
turbo-malloc = { path = "../turbo-malloc", optional = true, default-features = false }
turbo-tasks = { path = "../turbo-tasks" }
# turbo-tasks-memory = { path = "../turbo-tasks-memory", features = ["log_running_tasks", "log_scheduled_tasks", "log_activate_tasks", "log_connect_tasks"] }
turbo-tasks-memory = { path = "../turbo-tasks-memory" }
Expand Down
8 changes: 6 additions & 2 deletions crates/turbo-malloc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ autobenches = false
bench = false

[target.'cfg(not(target_os = "linux"))'.dependencies]
mimalloc = { version = "0.1.30" }
mimalloc = { version = "0.1.32", features = [], optional = true }

[target.'cfg(all(target_os = "linux", not(target_arch = "aarch64")))'.dependencies]
mimalloc = { version = "0.1.30", features = ["local_dynamic_tls"] }
mimalloc = { version = "0.1.32", features = ["local_dynamic_tls"], optional = true }

[features]
default = ["custom_allocator"]
custom_allocator = ["dep:mimalloc"]
72 changes: 72 additions & 0 deletions crates/turbo-malloc/src/counter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use std::{
cell::UnsafeCell,
ptr::NonNull,
sync::atomic::{AtomicUsize, Ordering},
};

pub static ALLOCATED: AtomicUsize = AtomicUsize::new(0);
const RESERVE: usize = 1000240; // 100 KiB
const MAX_RESERVE: usize = 2000480; // 200 KiB

struct ThreadLocalCounter {
reserved: usize,
}

impl ThreadLocalCounter {
fn add(&mut self, size: usize) {
if self.reserved >= size {
self.reserved -= size;
} else {
let offset = size - self.reserved + RESERVE;
self.reserved = RESERVE;
ALLOCATED.fetch_add(offset, Ordering::Relaxed);
}
}

fn remove(&mut self, size: usize) {
self.reserved += size;
if self.reserved > MAX_RESERVE {
let offset = self.reserved - RESERVE;
self.reserved = RESERVE;
ALLOCATED.fetch_sub(offset, Ordering::Relaxed);
}
}

fn unload(&mut self) {
if self.reserved > 0 {
ALLOCATED.fetch_sub(self.reserved, Ordering::Relaxed);
self.reserved = 0;
}
}
}

thread_local! {
static LOCAL_COUNTER: UnsafeCell<ThreadLocalCounter> = UnsafeCell::new(ThreadLocalCounter { reserved: 0 });
}

pub fn add(size: usize) {
LOCAL_COUNTER.with(|local| {
let ptr = local.get();
// SAFETY: This is a thread local.
let mut local = unsafe { NonNull::new_unchecked(ptr) };
unsafe { local.as_mut() }.add(size);
})
}

pub fn remove(size: usize) {
LOCAL_COUNTER.with(|local| {
let ptr = local.get();
// SAFETY: This is a thread local.
let mut local = unsafe { NonNull::new_unchecked(ptr) };
unsafe { local.as_mut() }.remove(size);
})
}

pub fn thread_stop() {
LOCAL_COUNTER.with(|local| {
let ptr = local.get();
// SAFETY: This is a thread local.
let mut local = unsafe { NonNull::new_unchecked(ptr) };
unsafe { local.as_mut() }.unload();
})
}
81 changes: 70 additions & 11 deletions crates/turbo-malloc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,102 @@
use std::alloc::{GlobalAlloc, Layout};
mod counter;

use std::{
alloc::{GlobalAlloc, Layout},
sync::atomic::Ordering,
};

use self::counter::{add, remove, thread_stop, ALLOCATED};

/// Turbo's preferred global allocator. This is a new type instead of a type
/// alias because you can't use type aliases to instantiate unit types (E0423).
pub struct TurboMalloc;

#[cfg(not(all(target_os = "linux", target_arch = "aarch64")))]
impl TurboMalloc {
pub fn memory_usage() -> usize {
ALLOCATED.load(Ordering::Relaxed)
}

pub fn thread_stop() {
thread_stop();
}
}

#[cfg(all(
feature = "custom_allocator",
not(all(target_os = "linux", target_arch = "aarch64"))
))]
unsafe impl GlobalAlloc for TurboMalloc {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
mimalloc::MiMalloc.alloc(layout)
let ret = mimalloc::MiMalloc.alloc(layout);
if !ret.is_null() {
add(layout.size());
}
ret
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
mimalloc::MiMalloc.dealloc(ptr, layout)
mimalloc::MiMalloc.dealloc(ptr, layout);
remove(layout.size());
}

unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
mimalloc::MiMalloc.alloc_zeroed(layout)
let ret = mimalloc::MiMalloc.alloc_zeroed(layout);
if ret.is_null() {
add(layout.size());
}
ret
}

unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
mimalloc::MiMalloc.realloc(ptr, layout, new_size)
let ret = mimalloc::MiMalloc.realloc(ptr, layout, new_size);
if !ret.is_null() {
let old_size = layout.size();
if old_size < new_size {
add(new_size - old_size);
} else {
remove(old_size - new_size);
}
}
ret
}
}

#[cfg(all(target_os = "linux", target_arch = "aarch64"))]
#[cfg(any(
not(feature = "custom_allocator"),
all(target_os = "linux", target_arch = "aarch64")
))]
unsafe impl GlobalAlloc for TurboMalloc {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
std::alloc::System.alloc(layout)
let ret = std::alloc::System.alloc(layout);
if !ret.is_null() {
add(layout.size());
}
ret
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
std::alloc::System.dealloc(ptr, layout)
std::alloc::System.dealloc(ptr, layout);
remove(layout.size());
}

unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
std::alloc::System.alloc_zeroed(layout)
let ret = std::alloc::System.alloc_zeroed(layout);
if ret.is_null() {
add(layout.size());
}
ret
}

unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
std::alloc::System.realloc(ptr, layout, new_size)
let ret = std::alloc::System.realloc(ptr, layout, new_size);
if !ret.is_null() {
let old_size = layout.size();
if old_size < new_size {
add(new_size - old_size);
} else {
remove(old_size - new_size);
}
}
ret
}
}
18 changes: 18 additions & 0 deletions crates/turbo-tasks/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,21 @@ impl Debug for FormatDuration {
write!(f, "{}ms", (self.0.as_micros() as f32) / 1000.0)
}
}

pub struct FormatBytes(pub usize);

impl Display for FormatBytes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let b = self.0;
if b > 1_000_000_000 {
return write!(f, "{:.2}GB", ((b / 1_000_000) as f32) / 1_000.0);
}
if b > 1_000_000 {
return write!(f, "{:.2}MB", ((b / 1_000) as f32) / 1_000.0);
}
if b > 1_000 {
return write!(f, "{:.2}KB", (b as f32) / 1_000.0);
}
write!(f, "{}B", b)
}
}

0 comments on commit 804a428

Please sign in to comment.