Skip to content

Commit

Permalink
perf(allocator): Use std instead of allocator-api2 (#9281)
Browse files Browse the repository at this point in the history
**Description:**

`std` is faster.
  • Loading branch information
kdy1 authored Jul 19, 2024
1 parent 85f158b commit 88723db
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 57 deletions.
5 changes: 0 additions & 5 deletions Cargo.lock

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

6 changes: 2 additions & 4 deletions crates/swc_allocator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ version = "0.1.7"

[features]
default = ["scoped"]
nightly = []
nightly = ["bumpalo/allocator_api"]
rkyv = ["dep:rkyv"]
scoped = ["nightly"]
serde = ["dep:serde", "dep:serde_derive", "allocator-api2/serde"]
serde = ["dep:serde"]

[dependencies]
allocator-api2 = { workspace = true }
bumpalo = { workspace = true, features = [
"boxed",
"collections",
Expand All @@ -30,7 +29,6 @@ bumpalo = { workspace = true, features = [
ptr_meta = { workspace = true }
rkyv = { workspace = true, optional = true }
serde = { workspace = true, optional = true }
serde_derive = { workspace = true, optional = true }
triomphe = { workspace = true }


Expand Down
49 changes: 28 additions & 21 deletions crates/swc_allocator/src/alloc.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
use std::{
alloc::Layout,
cell::Cell,
mem::transmute,
ops::{Deref, DerefMut},
ptr::NonNull,
};

use allocator_api2::alloc::AllocError;
#[cfg(feature = "nightly")]
use std::alloc::{AllocError, Layout};
#[cfg(feature = "scoped")]
use std::cell::Cell;
#[cfg(feature = "scoped")]
use std::mem::transmute;
use std::ops::{Deref, DerefMut};
#[cfg(feature = "nightly")]
use std::ptr::NonNull;

use bumpalo::Bump;

use crate::FastAlloc;

#[cfg(feature = "scoped")]
thread_local! {
static ALLOC: Cell<Option<&'static Allocator>> = const { Cell::new(None) };
}
Expand All @@ -22,11 +24,13 @@ pub struct Allocator {
}

pub struct AllocGuard {
#[cfg(feature = "scoped")]
orig: Option<&'static Allocator>,
}

impl Drop for AllocGuard {
fn drop(&mut self) {
#[cfg(feature = "scoped")]
ALLOC.set(self.orig.take());
}
}
Expand All @@ -39,15 +43,21 @@ impl Allocator {
/// [Allocator] must outlive [crate::boxed::Box] and [crate::vec::Vec]
/// created while the guard is active.
pub unsafe fn guard(&self) -> AllocGuard {
#[cfg(feature = "scoped")]
let orig = ALLOC.get();

#[cfg(feature = "scoped")]
let s = unsafe {
// Safery: We are using a scoped API
transmute::<&Allocator, &'static Allocator>(self)
};

#[cfg(feature = "scoped")]
ALLOC.set(Some(s));
AllocGuard { orig }
AllocGuard {
#[cfg(feature = "scoped")]
orig,
}
}
}

Expand All @@ -66,27 +76,24 @@ impl Default for FastAlloc {

impl FastAlloc {
/// `true` is passed to `f` if the box is allocated with a custom allocator.
fn with_allocator<T>(
&self,
f: impl FnOnce(&dyn allocator_api2::alloc::Allocator, bool) -> T,
) -> T {
#[cfg(feature = "nightly")]
fn with_allocator<T>(&self, f: impl FnOnce(&dyn std::alloc::Allocator, bool) -> T) -> T {
#[cfg(feature = "scoped")]
if let Some(arena) = &self.alloc {
return f(
(&&arena.alloc) as &dyn allocator_api2::alloc::Allocator,
true,
);
return f((&&arena.alloc) as &dyn std::alloc::Allocator, true);
}

f(&allocator_api2::alloc::Global, false)
f(&std::alloc::Global, false)
}
}

#[cfg(feature = "nightly")]
fn mark_ptr_as_arena_mode(ptr: NonNull<[u8]>) -> NonNull<[u8]> {
ptr
}

unsafe impl allocator_api2::alloc::Allocator for FastAlloc {
#[cfg(feature = "nightly")]
unsafe impl std::alloc::Allocator for FastAlloc {
#[inline]
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
self.with_allocator(|a, is_arena_mode| {
Expand Down Expand Up @@ -121,7 +128,7 @@ unsafe impl allocator_api2::alloc::Allocator for FastAlloc {
return;
}

allocator_api2::alloc::Global.deallocate(ptr, layout)
std::alloc::Global.deallocate(ptr, layout)
}

#[inline]
Expand Down
17 changes: 7 additions & 10 deletions crates/swc_allocator/src/boxed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ mod serde;
/// Faster alterantive for [`std::boxed::Box`].
#[repr(transparent)]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Box<T: ?Sized>(pub(crate) allocator_api2::boxed::Box<T, FastAlloc>);
pub struct Box<T: ?Sized>(pub(crate) std::boxed::Box<T, FastAlloc>);

impl<T> From<T> for Box<T> {
#[inline(always)]
Expand All @@ -28,9 +28,9 @@ impl<T> From<T> for Box<T> {
}
}

impl<T: ?Sized> From<allocator_api2::boxed::Box<T, FastAlloc>> for Box<T> {
impl<T: ?Sized> From<std::boxed::Box<T, FastAlloc>> for Box<T> {
#[inline(always)]
fn from(v: allocator_api2::boxed::Box<T, FastAlloc>) -> Self {
fn from(v: std::boxed::Box<T, FastAlloc>) -> Self {
Box(v)
}
}
Expand Down Expand Up @@ -76,12 +76,12 @@ impl<T> Box<T> {
/// ```
#[inline(always)]
pub fn new_in(value: T, alloc: FastAlloc) -> Self {
Self(allocator_api2::boxed::Box::new_in(value, alloc))
Self(std::boxed::Box::new_in(value, alloc))
}

/// Moves the value out of the box.
pub fn unbox(self) -> T {
allocator_api2::boxed::Box::into_inner(self.0)
std::boxed::Box::into_inner(self.0)
}
}

Expand Down Expand Up @@ -128,10 +128,7 @@ impl<T: ?Sized> Box<T> {
/// [memory layout]: self#memory-layout
/// [`Layout`]: crate::Layout
pub unsafe fn from_raw(raw: *mut T) -> Self {
Self(allocator_api2::boxed::Box::from_raw_in(
raw,
FastAlloc::default(),
))
Self(std::boxed::Box::from_raw_in(raw, FastAlloc::default()))
}

/// Consumes the `Box`, returning a wrapped raw pointer.
Expand Down Expand Up @@ -182,7 +179,7 @@ impl<T: ?Sized> Box<T> {
///
/// [memory layout]: self#memory-layout
pub fn into_raw(b: Self) -> *mut T {
allocator_api2::boxed::Box::into_raw(b.0)
std::boxed::Box::into_raw(b.0)
}

/// Converts a `Box<T>` into a `Pin<Box<T>>`. If `T` does not implement
Expand Down
2 changes: 1 addition & 1 deletion crates/swc_allocator/src/boxed/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ where
where
D: Deserializer<'de>,
{
Ok(Box(allocator_api2::boxed::Box::deserialize(deserializer)?))
Ok(Box::new(T::deserialize(deserializer)?))
}
}
8 changes: 4 additions & 4 deletions crates/swc_allocator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(
feature = "nightly",
feature(allocator_api, fundamental, with_negative_coherence)
feature(allocator_api, fundamental, with_negative_coherence, box_into_inner)
)]
#![deny(missing_docs)]
#![allow(clippy::derivable_impls)]
Expand Down Expand Up @@ -66,9 +66,9 @@ pub mod maybe {
///
/// # Misc
///
/// It implements [`allocator_api2::alloc::Allocator`]. So it can be used as the
/// second argument for [`allocator_api2::boxed::Box`] and
/// [`allocator_api2::vec::Vec`]. But you should prefer using
/// It implements [`std::alloc::Allocator`]. So it can be used as the
/// second argument for [`std::boxed::Box`] and
/// [`std::vec::Vec`]. But you should prefer using
/// [`crate::boxed::Box`] and [`crate::vec::Vec`], which is a wrapper around the
/// original types.
#[derive(Clone, Copy)]
Expand Down
Loading

0 comments on commit 88723db

Please sign in to comment.