Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move memory stats gathering from polkadot to parity-util-mem #588

Merged
merged 3 commits into from
Sep 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion parity-util-mem/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ The format is based on [Keep a Changelog].

[Keep a Changelog]: http://keepachangelog.com/en/1.0.0/

## [Unreleased]
## [0.10.1] - 2021-09-15
- Added support for memory stats gathering, ported over from `polkadot`. [#588](https://github.com/paritytech/parity-common/pull/588)

## [0.10.0] - 2021-07-02
- Fixed `malloc_usable_size` for FreeBSD. [#553](https://github.com/paritytech/parity-common/pull/553)

### Breaking
Expand Down
8 changes: 6 additions & 2 deletions parity-util-mem/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "parity-util-mem"
version = "0.10.0"
version = "0.10.1"
authors = ["Parity Technologies <admin@parity.io>"]
repository = "https://github.com/paritytech/parity-common"
description = "Collection of memory related utilities"
Expand Down Expand Up @@ -37,6 +37,10 @@ winapi = { version = "0.3.8", features = ["heapapi"] }
version = "0.3.2"
optional = true

[target.'cfg(not(target_os = "windows"))'.dependencies.jemalloc-ctl]
version = "0.3.3"
optional = true

[features]
default = ["std", "ethereum-impls", "lru", "hashbrown", "smallvec", "primitive-types"]
std = ["parking_lot"]
Expand All @@ -45,7 +49,7 @@ dlmalloc-global = ["dlmalloc", "estimate-heapsize"]
# use wee_alloc as global allocator
weealloc-global = ["wee_alloc", "estimate-heapsize"]
# use jemalloc as global allocator
jemalloc-global = ["jemallocator"]
jemalloc-global = ["jemallocator", "jemalloc-ctl"]
# use mimalloc as global allocator
mimalloc-global = ["mimalloc", "libmimalloc-sys"]
# implement additional types
Expand Down
56 changes: 56 additions & 0 deletions parity-util-mem/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,37 @@ cfg_if::cfg_if! {
/// Global allocator
#[global_allocator]
pub static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

mod memory_stats_jemalloc;
use memory_stats_jemalloc as memory_stats;
ordian marked this conversation as resolved.
Show resolved Hide resolved
} else if #[cfg(feature = "dlmalloc-global")] {
/// Global allocator
#[global_allocator]
pub static ALLOC: dlmalloc::GlobalDlmalloc = dlmalloc::GlobalDlmalloc;

mod memory_stats_noop;
use memory_stats_noop as memory_stats;
} else if #[cfg(feature = "weealloc-global")] {
/// Global allocator
#[global_allocator]
pub static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

mod memory_stats_noop;
use memory_stats_noop as memory_stats;
} else if #[cfg(all(
feature = "mimalloc-global",
not(target_arch = "wasm32")
))] {
/// Global allocator
#[global_allocator]
pub static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;

mod memory_stats_noop;
use memory_stats_noop as memory_stats;
} else {
// default allocator used
mod memory_stats_noop;
use memory_stats_noop as memory_stats;
}
}

Expand Down Expand Up @@ -78,6 +92,48 @@ pub fn malloc_size<T: MallocSizeOf + ?Sized>(t: &T) -> usize {
MallocSizeOf::size_of(t, &mut allocators::new_malloc_size_ops())
}

/// An error related to the memory stats gathering.
#[derive(Clone, Debug)]
pub struct MemoryStatsError(memory_stats::Error);

#[cfg(feature = "std")]
impl std::fmt::Display for MemoryStatsError {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
self.0.fmt(fmt)
}
}

#[cfg(feature = "std")]
impl std::error::Error for MemoryStatsError {}

/// Snapshot of collected memory metrics.
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct MemoryAllocationSnapshot {
/// Total resident memory, in bytes.
pub resident: u64,
/// Total allocated memory, in bytes.
pub allocated: u64,
}

/// Accessor to the allocator internals.
#[derive(Clone)]
pub struct MemoryAllocationTracker(self::memory_stats::MemoryAllocationTracker);

impl MemoryAllocationTracker {
/// Create an instance of an allocation tracker.
pub fn new() -> Result<Self, MemoryStatsError> {
self::memory_stats::MemoryAllocationTracker::new()
.map(MemoryAllocationTracker)
.map_err(MemoryStatsError)
}

/// Create an allocation snapshot.
pub fn snapshot(&self) -> Result<MemoryAllocationSnapshot, MemoryStatsError> {
self.0.snapshot().map_err(MemoryStatsError)
}
}

#[cfg(feature = "std")]
#[cfg(test)]
mod test {
Expand Down
32 changes: 32 additions & 0 deletions parity-util-mem/src/memory_stats_jemalloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2021 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub use jemalloc_ctl::Error;
use jemalloc_ctl::{epoch, stats};

#[derive(Clone)]
pub struct MemoryAllocationTracker {
epoch: jemalloc_ctl::epoch_mib,
allocated: stats::allocated_mib,
resident: stats::resident_mib,
}

impl MemoryAllocationTracker {
pub fn new() -> Result<Self, Error> {
Ok(Self { epoch: epoch::mib()?, allocated: stats::allocated::mib()?, resident: stats::resident::mib()? })
}

pub fn snapshot(&self) -> Result<crate::MemoryAllocationSnapshot, Error> {
// update stats by advancing the allocation epoch
self.epoch.advance()?;

let allocated: u64 = self.allocated.read()? as _;
let resident: u64 = self.resident.read()? as _;
Ok(crate::MemoryAllocationSnapshot { allocated, resident })
}
}
31 changes: 31 additions & 0 deletions parity-util-mem/src/memory_stats_noop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2021 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[derive(Clone, Debug)]
pub struct Unimplemented;
pub use Unimplemented as Error;

#[cfg(feature = "std")]
impl std::fmt::Display for Unimplemented {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.write_str("unimplemented")
}
}

#[derive(Clone)]
pub struct MemoryAllocationTracker {}

impl MemoryAllocationTracker {
pub fn new() -> Result<Self, Error> {
Err(Error)
}

pub fn snapshot(&self) -> Result<crate::MemoryAllocationSnapshot, Error> {
unimplemented!();
ordian marked this conversation as resolved.
Show resolved Hide resolved
}
}