Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

[DNM] Wrapper allocator PoC #7206

Draft
wants to merge 39 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
d86bd79
Implement wrapper allocator -- draft
s0me0ne-unkn0wn May 6, 2023
998a6ff
Minor fixes
s0me0ne-unkn0wn May 9, 2023
dbd40a7
Backlog tracking allocator
s0me0ne-unkn0wn May 18, 2023
c8e9d1c
Try spinlock approach
s0me0ne-unkn0wn May 19, 2023
b841129
Rename things
s0me0ne-unkn0wn May 19, 2023
d3e3e72
Merge remote-tracking branch 'origin/master' into s0me0ne/wrapper-all…
s0me0ne-unkn0wn May 19, 2023
089e6d8
Fix feature name
s0me0ne-unkn0wn May 22, 2023
818699a
Add a benchmark to measure Kusama runtime preparation time
s0me0ne-unkn0wn May 22, 2023
052b096
Merge remote-tracking branch 'origin/master' into s0me0ne/wrapper-all…
s0me0ne-unkn0wn Jun 5, 2023
66e8a8b
Merge remote-tracking branch 'origin/master' into s0me0ne/wrapper-all…
s0me0ne-unkn0wn Aug 1, 2023
dbdeb52
".git/.scripts/commands/fmt/fmt.sh"
Aug 1, 2023
1dfd9ca
` XcmContext` to `buy_weight / refund_weight` (#7563)
bkontur Aug 1, 2023
152888f
Take into account size as well in weight limiting. (#7369)
eskimor Aug 1, 2023
70aed93
[companion] Get rid of `Peerset` compatibility layer (#7355)
dmitry-markin Aug 2, 2023
88c1a70
Companion for Substrate#14373 (#7572)
drskalman Aug 2, 2023
b137472
[xcm] `GlobalConsensusConvertsFor` for remote relay chain (based on p…
bkontur Aug 3, 2023
b810ce4
Fix flaky reputation change test (#7550)
AndreiEres Aug 4, 2023
314e519
Add license to crates (#7578)
Morganamilo Aug 4, 2023
62b489f
Remove xcm on_runtime_upgrade pallet hook (#7235)
pgherveou Aug 5, 2023
14e6605
Document non-uniqueness of SetTopic IDs (#7579)
KiChjang Aug 7, 2023
929e2d4
PVF: Add missing crate descriptions (#7587)
mrcnski Aug 8, 2023
06ccdf2
update weight file template (#7589)
xlc Aug 8, 2023
aaea117
Companion for #14412 (#7547)
davxy Aug 9, 2023
c7bbfba
Remove unused code in runtime/polkadot/src/lib.rs (#7540)
liamaharon Aug 10, 2023
08f4333
Companion for substrate#12970 (#6807)
gpestana Aug 10, 2023
0f27b6c
Add counter for unapproved candidates (#7491)
AndreiEres Aug 10, 2023
e813323
Publish RC container images (#7556)
chevdor Aug 11, 2023
12fdcba
companion for 14754: cli: move no-beefy flag to sc-cli (#7600)
acatangiu Aug 11, 2023
0f57383
pvf: use test-utils feature to export test only (#7538)
jpserrat Aug 14, 2023
2dda590
RC container image fixes (#7607)
chevdor Aug 14, 2023
730a1c8
Fix the user used to login to Docker hub (#7610)
chevdor Aug 14, 2023
04ae532
Remove ParityDb migration tests (#7612)
altonen Aug 14, 2023
6f9fe26
Use same `fmt` and `clippy` configs as in Substrate (#7611)
ggwpez Aug 14, 2023
ffb8d15
Disable validation/collation protocols for normal full nodes (#7601)
altonen Aug 14, 2023
74b2fec
Don't publish test crates (#7588)
Morganamilo Aug 14, 2023
2a2393f
PVF workers: some fixes for cargo run and cargo install (#7608)
mrcnski Aug 14, 2023
ed8f0f8
XCM: Rename Instruction instructions to Command instructions (#7593)
KiChjang Aug 14, 2023
4f47d3c
Remove superflous parameter `overseer_enable_anyways` and make parach…
bkchr Aug 15, 2023
d25f550
Merge remote-tracking branch 'origin/master' into s0me0ne/wrapper-all…
s0me0ne-unkn0wn Aug 15, 2023
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
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ polkadot-cli = { path = "cli", features = [ "polkadot-native", "kusama-native",
polkadot-node-core-pvf = { path = "node/core/pvf" }
polkadot-node-core-pvf-prepare-worker = { path = "node/core/pvf/prepare-worker" }
polkadot-overseer = { path = "node/overseer" }
tracking-allocator = { path = "node/tracking-allocator", optional = true }

# Needed for worker binaries.
polkadot-node-core-pvf-common = { path = "node/core/pvf/common", features = ["test-utils"] }
Expand Down Expand Up @@ -121,6 +122,7 @@ members = [
"node/subsystem-types",
"node/subsystem-test-helpers",
"node/subsystem-util",
"node/tracking-allocator",
"node/jaeger",
"node/gum",
"node/gum/proc-macro",
Expand Down Expand Up @@ -227,6 +229,8 @@ fast-runtime = [ "polkadot-cli/fast-runtime" ]
runtime-metrics = [ "polkadot-cli/runtime-metrics" ]
pyroscope = ["polkadot-cli/pyroscope"]
jemalloc-allocator = ["polkadot-node-core-pvf-prepare-worker/jemalloc-allocator", "polkadot-overseer/jemalloc-allocator"]
tracking-allocator = ["jemalloc-allocator", "dep:tracking-allocator", "polkadot-node-core-pvf-prepare-worker/tracking-allocator"]

# Enables timeout-based tests supposed to be run only in CI environment as they may be flaky
# when run locally depending on system load
ci-only-tests = ["polkadot-node-core-pvf/ci-only-tests"]
Expand Down
5 changes: 0 additions & 5 deletions cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,6 @@ pub struct RunCmd {
#[arg(long = "grandpa-pause", num_args = 2)]
pub grandpa_pause: Vec<u32>,

/// Disable the BEEFY gadget
/// (currently enabled by default on Rococo, Wococo and Versi).
#[arg(long)]
pub no_beefy: bool,

/// Add the destination address to the jaeger agent.
///
/// Must be valid socket address, of format `IP:Port`
Expand Down
11 changes: 5 additions & 6 deletions cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,11 @@ fn run_node_inner<F>(
where
F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration),
{
let runner = cli
let mut runner = cli
.create_runner_with_logger_hook::<sc_cli::RunCmd, F>(&cli.run.base, logger_hook)
.map_err(Error::from)?;
let chain_spec = &runner.config().chain_spec;

// By default, enable BEEFY on test networks.
let enable_beefy = (chain_spec.is_rococo() || chain_spec.is_wococo() || chain_spec.is_versi()) &&
!cli.run.no_beefy;

set_default_ss58_version(chain_spec);

let grandpa_pause = if cli.run.grandpa_pause.is_empty() {
Expand All @@ -259,6 +255,10 @@ where
info!(" KUSAMA FOUNDATION ");
info!("----------------------------");
}
// BEEFY allowed only on test networks.
if !(chain_spec.is_rococo() || chain_spec.is_wococo() || chain_spec.is_versi()) {
runner.config_mut().disable_beefy = true;
}

let jaeger_agent = if let Some(ref jaeger_agent) = cli.run.jaeger_agent {
Some(
Expand Down Expand Up @@ -289,7 +289,6 @@ where
service::NewFullParams {
is_parachain_node: service::IsParachainNode::No,
grandpa_pause,
enable_beefy,
jaeger_agent,
telemetry_worker_handle: None,
node_version,
Expand Down
10 changes: 10 additions & 0 deletions node/core/pvf/prepare-worker/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ libc = "0.2.139"
rayon = "1.5.1"
tikv-jemalloc-ctl = { version = "0.5.0", optional = true }
tokio = { version = "1.24.2", features = ["fs", "process"] }
tracking-allocator = { path = "../../../tracking-allocator", optional = true }

parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] }

Expand All @@ -33,3 +34,12 @@ tikv-jemalloc-ctl = "0.5.0"
[features]
builder = []
jemalloc-allocator = ["dep:tikv-jemalloc-ctl"]
tracking-allocator = ["dep:tracking-allocator"]

[dev-dependencies]
criterion = { version = "0.4.0", default-features = false, features = ["cargo_bench_support"] }
kusama-runtime = { path = "../../../../runtime/kusama" }

[[bench]]
name = "prepare_kusama_runtime"
harness = false
60 changes: 60 additions & 0 deletions node/core/pvf/prepare-worker/benches/prepare_kusama_runtime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot 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.

// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.

use criterion::{criterion_group, criterion_main, Criterion, SamplingMode};
use polkadot_node_core_pvf_common::{prepare::PrepareJobKind, pvf::PvfPrepData};
use polkadot_node_core_pvf_prepare_worker::{prepare, prevalidate};
use polkadot_primitives::ExecutorParams;
use std::time::Duration;

fn do_prepare_kusama_runtime(pvf: PvfPrepData) {
let blob = match prevalidate(&pvf.code()) {
Err(err) => panic!("{:?}", err),
Ok(b) => b,
};

match prepare(blob, &pvf.executor_params()) {
Ok(_) => (),
Err(err) => panic!("{:?}", err),
}
}

fn prepare_kusama_runtime(c: &mut Criterion) {
let blob = kusama_runtime::WASM_BINARY.unwrap();
let pvf = match sp_maybe_compressed_blob::decompress(&blob, 64 * 1024 * 1024) {
Ok(code) => PvfPrepData::from_code(
code.into_owned(),
ExecutorParams::default(),
Duration::from_secs(360),
PrepareJobKind::Compilation,
),
Err(e) => {
panic!("Cannot decompress blob: {:?}", e);
},
};

let mut group = c.benchmark_group("kusama");
group.sampling_mode(SamplingMode::Flat);
group.sample_size(20);
group.measurement_time(Duration::from_secs(240));
group.bench_function("prepare Kusama runtime", |b| {
b.iter(|| do_prepare_kusama_runtime(pvf.clone()))
});
group.finish();
}

criterion_group!(preparation, prepare_kusama_runtime);
criterion_main!(preparation);
16 changes: 16 additions & 0 deletions node/core/pvf/prepare-worker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ use std::{
time::Duration,
};
use tokio::{io, net::UnixStream};
#[cfg(feature = "tracking-allocator")]
use tracking_allocator::ALLOC;

/// Contains the bytes for a successfully compiled artifact.
pub struct CompiledArtifact(Vec<u8>);
Expand Down Expand Up @@ -180,9 +182,23 @@ pub fn worker_entrypoint(
#[cfg(not(target_os = "linux"))]
let landlock_status: Result<LandlockStatus, String> = Ok(LandlockStatus::NotEnforced);

#[cfg(feature = "tracking-allocator")]
ALLOC.start_tracking();

#[allow(unused_mut)]
let mut result = prepare_artifact(pvf, cpu_time_start);

#[cfg(feature = "tracking-allocator")]
{
let peak = ALLOC.end_tracking();
gum::debug!(
target: LOG_TARGET,
%worker_pid,
"prepare job peak allocation is {} bytes",
peak,
);
}

// Get the `ru_maxrss` stat. If supported, call getrusage for the thread.
#[cfg(target_os = "linux")]
let mut result = result
Expand Down
3 changes: 1 addition & 2 deletions node/service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,6 @@ where
pub struct NewFullParams<OverseerGenerator: OverseerGen> {
pub is_parachain_node: IsParachainNode,
pub grandpa_pause: Option<(u32, u32)>,
pub enable_beefy: bool,
pub jaeger_agent: Option<std::net::SocketAddr>,
pub telemetry_worker_handle: Option<TelemetryWorkerHandle>,
/// The version of the node. TESTING ONLY: `None` can be passed to skip the node/worker version
Expand Down Expand Up @@ -720,7 +719,6 @@ pub fn new_full<OverseerGenerator: OverseerGen>(
NewFullParams {
is_parachain_node,
grandpa_pause,
enable_beefy,
jaeger_agent,
telemetry_worker_handle,
node_version,
Expand Down Expand Up @@ -754,6 +752,7 @@ pub fn new_full<OverseerGenerator: OverseerGen>(
Some(backoff)
};

let enable_beefy = !config.disable_beefy;
// If not on a known test network, warn the user that BEEFY is still experimental.
if enable_beefy &&
!config.chain_spec.is_rococo() &&
Expand Down
2 changes: 1 addition & 1 deletion node/test/service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ pub fn new_full(
polkadot_service::NewFullParams {
is_parachain_node,
grandpa_pause: None,
enable_beefy: true,
jaeger_agent: None,
telemetry_worker_handle: None,
node_version: None,
Expand Down Expand Up @@ -187,6 +186,7 @@ pub fn node_config(
offchain_worker: Default::default(),
force_authoring: false,
disable_grandpa: false,
disable_beefy: false,
dev_key_seed: Some(key_seed),
tracing_targets: None,
tracing_receiver: Default::default(),
Expand Down
9 changes: 9 additions & 0 deletions node/tracking-allocator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "tracking-allocator"
description = "Tracking allocator to control amount of memory consumed by PVF preparation process"
version.workspace = true
authors.workspace = true
edition.workspace = true

[dependencies]
tikv-jemallocator = "0.5.0"
136 changes: 136 additions & 0 deletions node/tracking-allocator/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot 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.

// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.

//! Tracking global allocator. Calculates the peak allocation between two checkpoints.

use core::alloc::{GlobalAlloc, Layout};
use std::sync::atomic::{AtomicBool, Ordering};
use tikv_jemallocator::Jemalloc;

struct TrackingAllocatorData {
lock: AtomicBool,
current: isize,
peak: isize,
}

impl TrackingAllocatorData {
#[inline]
fn lock(&self) {
loop {
// Try to acquire the lock.
if self
.lock
.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_ok()
{
break
}
// We failed to acquire the lock; wait until it's unlocked.
//
// In theory this should result in less coherency traffic as unlike `compare_exchange`
// it is a read-only operation, so multiple cores can execute it simultaneously
// without taking an exclusive lock over the cache line.
while self.lock.load(Ordering::Relaxed) {
std::hint::spin_loop();
}
}
}

#[inline]
fn unlock(&self) {
self.lock.store(false, Ordering::Release);
}

fn start_tracking(&mut self) {
self.lock();
self.current = 0;
self.peak = 0;
self.unlock();
}

fn end_tracking(&self) -> isize {
self.lock();
let peak = self.peak;
self.unlock();
peak
}

#[inline]
fn track(&mut self, alloc: isize) {
self.lock();
self.current += alloc;
if self.current > self.peak {
self.peak = self.current;
}
self.unlock();
}
}

static mut ALLOCATOR_DATA: TrackingAllocatorData =
TrackingAllocatorData { lock: AtomicBool::new(false), current: 0, peak: 0 };

pub struct TrackingAllocator<A: GlobalAlloc>(A);

impl<A: GlobalAlloc> TrackingAllocator<A> {
// SAFETY:
// * The following functions write to `static mut`. That is safe as the critical section
// inside is isolated by an exclusive lock.

/// Start tracking
pub fn start_tracking(&self) {
unsafe {
ALLOCATOR_DATA.start_tracking();
}
}

/// End tracking and return the peak allocation value in bytes (as `isize`). Peak allocation
/// value is not guaranteed to be neither non-zero nor positive.
pub fn end_tracking(&self) -> isize {
unsafe { ALLOCATOR_DATA.end_tracking() }
}
}

unsafe impl<A: GlobalAlloc> GlobalAlloc for TrackingAllocator<A> {
// SAFETY:
// * The wrapped methods are as safe as the underlying allocator implementation is

#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ALLOCATOR_DATA.track(layout.size() as isize);
self.0.alloc(layout)
}

#[inline]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
ALLOCATOR_DATA.track(layout.size() as isize);
self.0.alloc_zeroed(layout)
}

#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) -> () {
ALLOCATOR_DATA.track(-(layout.size() as isize));
self.0.dealloc(ptr, layout)
}

#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
ALLOCATOR_DATA.track((new_size as isize) - (layout.size() as isize));
self.0.realloc(ptr, layout, new_size)
}
}

#[global_allocator]
pub static ALLOC: TrackingAllocator<Jemalloc> = TrackingAllocator(Jemalloc);
5 changes: 4 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ use color_eyre::eyre;

/// Global allocator. Changing it to another allocator will require changing
/// `memory_stats::MemoryAllocationTracker`.
#[cfg(any(target_os = "linux", feature = "jemalloc-allocator"))]
#[cfg(all(
any(target_os = "linux", feature = "jemalloc-allocator"),
not(feature = "wrapper-allocator")
))]
#[global_allocator]
pub static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;

Expand Down
Loading