Skip to content

Commit

Permalink
Merge pull request #2124 from subspace/farmer-audit-benchmark
Browse files Browse the repository at this point in the history
Farmer audit benchmark
  • Loading branch information
nazar-pc authored Oct 16, 2023
2 parents 538d262 + 005157e commit 7ea0f61
Show file tree
Hide file tree
Showing 20 changed files with 633 additions and 341 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion crates/pallet-subspace/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ fn erasure_coding_instance() -> &'static ErasureCoding {

ERASURE_CODING.get_or_init(|| {
ErasureCoding::new(
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize).unwrap(),
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize)
.expect("Not zero; qed"),
)
.unwrap()
})
Expand Down
3 changes: 2 additions & 1 deletion crates/sp-lightclient/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ fn erasure_coding_instance() -> &'static ErasureCoding {

ERASURE_CODING.get_or_init(|| {
ErasureCoding::new(
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize).unwrap(),
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize)
.expect("Not zero; qed"),
)
.unwrap()
})
Expand Down
3 changes: 2 additions & 1 deletion crates/subspace-farmer-components/benches/auditing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let kzg = Kzg::new(kzg::embedded_kzg_settings());
let mut archiver = Archiver::new(kzg.clone()).unwrap();
let erasure_coding = ErasureCoding::new(
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize).unwrap(),
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize)
.expect("Not zero; qed"),
)
.unwrap();
let mut table_generator = PosTable::generator();
Expand Down
3 changes: 2 additions & 1 deletion crates/subspace-farmer-components/benches/plotting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ fn criterion_benchmark(c: &mut Criterion) {
let kzg = Kzg::new(kzg::embedded_kzg_settings());
let mut archiver = Archiver::new(kzg.clone()).unwrap();
let erasure_coding = ErasureCoding::new(
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize).unwrap(),
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize)
.expect("Not zero; qed"),
)
.unwrap();
let mut table_generator = PosTable::generator();
Expand Down
3 changes: 2 additions & 1 deletion crates/subspace-farmer-components/benches/proving.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let kzg = Kzg::new(kzg::embedded_kzg_settings());
let mut archiver = Archiver::new(kzg.clone()).unwrap();
let erasure_coding = ErasureCoding::new(
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize).unwrap(),
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize)
.expect("Not zero; qed"),
)
.unwrap();
let mut table_generator = PosTable::generator();
Expand Down
3 changes: 2 additions & 1 deletion crates/subspace-farmer-components/benches/reading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let kzg = Kzg::new(kzg::embedded_kzg_settings());
let mut archiver = Archiver::new(kzg.clone()).unwrap();
let erasure_coding = ErasureCoding::new(
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize).unwrap(),
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize)
.expect("Not zero; qed"),
)
.unwrap();
let mut table_generator = PosTable::generator();
Expand Down
1 change: 1 addition & 0 deletions crates/subspace-farmer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ blake2 = "0.10.6"
blake3 = { version = "1.4.1", default-features = false }
bytesize = "1.3.0"
clap = { version = "4.4.3", features = ["color", "derive"] }
criterion = { version = "0.5.1", default-features = false, features = ["rayon", "async"] }
derive_more = "0.99.17"
event-listener-primitives = "2.0.1"
fdlimit = "0.2"
Expand Down
5 changes: 5 additions & 0 deletions crates/subspace-farmer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ This will connect to local node and will try to solve on every slot notification

*NOTE: You need to have a `subspace-node` running before starting farmer, otherwise it will not be able to start*

### Benchmark auditing
```
target/production/subspace-farmer benchmark audit /path/to/farm
```

### Show information about the farm
```
target/production/subspace-farmer info /path/to/farm
Expand Down
4 changes: 2 additions & 2 deletions crates/subspace-farmer/src/bin/subspace-farmer/commands.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
mod farm;
pub(crate) mod benchmark;
pub(crate) mod farm;
mod info;
mod scrub;
mod shared;

pub(crate) use farm::farm;
pub(crate) use info::info;
pub(crate) use scrub::scrub;
141 changes: 141 additions & 0 deletions crates/subspace-farmer/src/bin/subspace-farmer/commands/benchmark.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
use crate::PosTable;
use anyhow::anyhow;
use clap::Subcommand;
use criterion::async_executor::AsyncExecutor;
use criterion::{black_box, BatchSize, Criterion, Throughput};
#[cfg(windows)]
use memmap2::Mmap;
use parking_lot::Mutex;
use std::fs::OpenOptions;
use std::future::Future;
use std::num::NonZeroUsize;
use std::path::PathBuf;
use subspace_core_primitives::crypto::kzg::{embedded_kzg_settings, Kzg};
use subspace_core_primitives::{Record, SolutionRange};
use subspace_erasure_coding::ErasureCoding;
use subspace_farmer::single_disk_farm::farming::{plot_audit, PlotAuditOptions};
use subspace_farmer::single_disk_farm::{SingleDiskFarm, SingleDiskFarmSummary};
use subspace_farmer_components::sector::sector_size;
use subspace_proof_of_space::Table;
use subspace_rpc_primitives::SlotInfo;
use tokio::runtime::Handle;

struct TokioAsyncExecutor(Handle);

impl AsyncExecutor for TokioAsyncExecutor {
fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
tokio::task::block_in_place(|| self.0.block_on(future))
}
}

impl TokioAsyncExecutor {
fn new() -> Self {
Self(Handle::current())
}
}

/// Arguments for benchmark
#[derive(Debug, Subcommand)]
pub(crate) enum BenchmarkArgs {
/// Audit benchmark
Audit {
/// Disk farm to audit
///
/// Example:
/// /path/to/directory
disk_farm: PathBuf,
#[arg(long, default_value_t = 10)]
sample_size: usize,
},
}

pub(crate) async fn benchmark(benchmark_args: BenchmarkArgs) -> anyhow::Result<()> {
match benchmark_args {
BenchmarkArgs::Audit {
disk_farm,
sample_size,
} => audit(disk_farm, sample_size).await,
}
}

async fn audit(disk_farm: PathBuf, sample_size: usize) -> anyhow::Result<()> {
let (single_disk_farm_info, disk_farm) = match SingleDiskFarm::collect_summary(disk_farm) {
SingleDiskFarmSummary::Found { info, directory } => (info, directory),
SingleDiskFarmSummary::NotFound { directory } => {
return Err(anyhow!(
"No single disk farm info found, make sure {} is a valid path to the farm and \
process have permissions to access it",
directory.display()
));
}
SingleDiskFarmSummary::Error { directory, error } => {
return Err(anyhow!(
"Failed to open single disk farm info, make sure {} is a valid path to the farm \
and process have permissions to access it: {error}",
directory.display()
));
}
};

let sector_size = sector_size(single_disk_farm_info.pieces_in_sector());
let kzg = Kzg::new(embedded_kzg_settings());
let erasure_coding = ErasureCoding::new(
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize)
.expect("Not zero; qed"),
)
.map_err(|error| anyhow::anyhow!(error))?;
let table_generator = Mutex::new(PosTable::generator());

let sectors_metadata = SingleDiskFarm::read_all_sectors_metadata(&disk_farm)
.map_err(|error| anyhow::anyhow!("Failed to read sectors metadata: {error}"))?;

let plot_file = OpenOptions::new()
.read(true)
.open(disk_farm.join(SingleDiskFarm::PLOT_FILE))
.map_err(|error| anyhow::anyhow!("Failed to open single disk farm: {error}"))?;
#[cfg(windows)]
let plot_mmap = unsafe { Mmap::map(&plot_file)? };

let mut criterion = Criterion::default().sample_size(sample_size);
criterion
.benchmark_group("audit")
.throughput(Throughput::Bytes(
sector_size as u64 * sectors_metadata.len() as u64,
))
.bench_function("plot", |b| {
b.to_async(TokioAsyncExecutor::new()).iter_batched(
rand::random,
|global_challenge| {
let options = PlotAuditOptions::<PosTable> {
public_key: single_disk_farm_info.public_key(),
reward_address: single_disk_farm_info.public_key(),
sector_size,
slot_info: SlotInfo {
slot_number: 0,
global_challenge,
// No solution will be found, pure audit
solution_range: SolutionRange::MIN,
// No solution will be found, pure audit
voting_solution_range: SolutionRange::MIN,
},
sectors_metadata: &sectors_metadata,
kzg: &kzg,
erasure_coding: &erasure_coding,
#[cfg(not(windows))]
plot_file: &plot_file,
#[cfg(windows)]
plot_mmap: &plot_mmap,
maybe_sector_being_modified: None,
table_generator: &table_generator,
};

black_box(plot_audit(black_box(options)))
},
BatchSize::SmallInput,
)
});

criterion.final_summary();

Ok(())
}
Loading

0 comments on commit 7ea0f61

Please sign in to comment.