146 lines
4.2 KiB
Rust
146 lines
4.2 KiB
Rust
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
|
// This file is part of Parity.
|
|
|
|
// Parity is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
|
|
// Parity is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//! default allocator management
|
|
//! Features are:
|
|
//! - windows:
|
|
//! - no features: default implementation from servo `heapsize` crate
|
|
//! - weealloc: default to `estimate_size`
|
|
//! - dlmalloc: default to `estimate_size`
|
|
//! - jemalloc: default windows allocator is used instead
|
|
//! - arch x86:
|
|
//! - no features: use default alloc
|
|
//! - jemalloc: use jemallocator crate
|
|
//! - weealloc: default to `estimate_size`
|
|
//! - dlmalloc: default to `estimate_size`
|
|
//! - arch wasm32:
|
|
//! - no features: default to `estimate_size`
|
|
//! - weealloc: default to `estimate_size`
|
|
//! - dlmalloc: default to `estimate_size`
|
|
//! - jemalloc: compile error
|
|
|
|
|
|
use malloc_size::{MallocSizeOfOps, VoidPtrToSizeFn, MallocSizeOf};
|
|
#[cfg(feature = "std")]
|
|
use malloc_size::MallocUnconditionalSizeOf;
|
|
#[cfg(feature = "std")]
|
|
use std::os::raw::c_void;
|
|
#[cfg(not(feature = "std"))]
|
|
use core::ffi::c_void;
|
|
#[cfg(not(feature = "std"))]
|
|
use alloc::collections::btree_set::BTreeSet;
|
|
|
|
mod usable_size {
|
|
|
|
use super::*;
|
|
|
|
cfg_if! {
|
|
|
|
if #[cfg(any(
|
|
target_arch = "wasm32",
|
|
feature = "estimate-heapsize",
|
|
feature = "weealloc-global",
|
|
feature = "dlmalloc-global",
|
|
))] {
|
|
|
|
// do not try system allocator
|
|
|
|
/// Warning this is for compatibility only.
|
|
/// This function does panic: `estimate-heapsize` feature needs to be activated
|
|
/// to avoid this function call.
|
|
pub unsafe extern "C" fn malloc_usable_size(_ptr: *const c_void) -> usize {
|
|
unreachable!("estimate heapsize only")
|
|
}
|
|
|
|
} else if #[cfg(target_os = "windows")] {
|
|
|
|
// default windows allocator
|
|
extern crate winapi;
|
|
|
|
use self::winapi::um::heapapi::{GetProcessHeap, HeapSize, HeapValidate};
|
|
|
|
/// Get the size of a heap block.
|
|
/// Call windows allocator through `winapi` crate
|
|
pub unsafe extern "C" fn malloc_usable_size(mut ptr: *const c_void) -> usize {
|
|
|
|
let heap = GetProcessHeap();
|
|
|
|
if HeapValidate(heap, 0, ptr) == 0 {
|
|
ptr = *(ptr as *const *const c_void).offset(-1);
|
|
}
|
|
|
|
HeapSize(heap, 0, ptr) as usize
|
|
}
|
|
|
|
} else if #[cfg(feature = "jemalloc-global")] {
|
|
|
|
/// Use of jemalloc usable size C function through jemallocator crate call.
|
|
pub unsafe extern "C" fn malloc_usable_size(ptr: *const c_void) -> usize {
|
|
jemallocator::usable_size(ptr)
|
|
}
|
|
|
|
} else {
|
|
|
|
// default allocator used
|
|
/// Macos, ios and android calls jemalloc.
|
|
/// Linux call system allocator (currently malloc).
|
|
extern "C" {
|
|
#[cfg_attr(any(prefixed_jemalloc, target_os = "macos", target_os = "ios", target_os = "android"), link_name = "je_malloc_usable_size")]
|
|
pub fn malloc_usable_size(ptr: *const c_void) -> usize;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// No enclosing function defined.
|
|
#[inline]
|
|
pub fn new_enclosing_size_fn() -> Option<VoidPtrToSizeFn> {
|
|
None
|
|
}
|
|
}
|
|
|
|
/// Get a new instance of a MallocSizeOfOps
|
|
pub fn new_malloc_size_ops() -> MallocSizeOfOps {
|
|
MallocSizeOfOps::new(
|
|
usable_size::malloc_usable_size,
|
|
usable_size::new_enclosing_size_fn(),
|
|
None,
|
|
)
|
|
}
|
|
|
|
/// Extension methods for `MallocSizeOf` trait, do not implement
|
|
/// directly.
|
|
/// It allows getting heapsize without exposing `MallocSizeOfOps`
|
|
/// (a single default `MallocSizeOfOps` is used for each call).
|
|
pub trait MallocSizeOfExt: MallocSizeOf {
|
|
/// Method to launch a heapsize measurement with a
|
|
/// fresh state.
|
|
fn malloc_size_of(&self) -> usize {
|
|
let mut ops = new_malloc_size_ops();
|
|
<Self as MallocSizeOf>::size_of(self, &mut ops)
|
|
}
|
|
}
|
|
|
|
impl<T: MallocSizeOf> MallocSizeOfExt for T { }
|
|
|
|
#[cfg(feature = "std")]
|
|
impl<T: MallocSizeOf> MallocSizeOf for std::sync::Arc<T> {
|
|
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
|
self.unconditional_size_of(ops)
|
|
}
|
|
}
|