Skip to content

Commit

Permalink
Merge pull request #8 from stackrox/feature/docs
Browse files Browse the repository at this point in the history
Add more documentation
  • Loading branch information
erthalion authored Oct 23, 2023
2 parents e3bd96a + 877ae05 commit 73d8499
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 49 deletions.
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,27 @@ workloads:
Poisson process.

Every workload is executed via set of worker processes, that are distributed
among available system CPU cores.
among available system CPU cores to fully utilize system resources.

# How to contribute

* Make sure you've got recent enough version of Rust compiler. At the moment
the minimal required version is 1.71 .

* Build project either directly using `cargo build`, or using containerized
version implemented as a make `all` target.

* Find out what you need to change. The rule of thumb: if it has something to
do with a specific workload type, it goes into a corresponding workload
module under the `worker` directory; if it's a general improvement, feel free
to modify anything outside workers.

* Do all sorts of hacking. Use `RUST_LOG=info` environment variable for getting
verbose output when troubleshooting.

* Make sure tests are passing, `cargo test`.

* Run linter, `cargo clippy`.

\[1\]: https://en.wikipedia.org/wiki/Poisson_point_process

Expand Down
71 changes: 62 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,90 @@
use core_affinity::CoreId;
use serde::Deserialize;
use std::fmt::Display;

pub mod worker;

/// Main workload configuration, contains general bits for all types of
/// workloads plus workload specific data.
#[derive(Debug, Copy, Clone, Deserialize)]
#[serde(tag = "distribution")]
pub enum Distribution {
#[serde(alias = "zipf")]
Zipfian { n_ports: u64, exponent: f64 },
#[serde(alias = "uniform")]
Uniform { lower: u64, upper: u64 },
pub struct WorkloadConfig {
/// An amount of time for workload payload to run before restarting.
pub restart_interval: u64,

/// Custom workload configuration.
pub workload: Workload,
}

/// Workload specific configuration, contains one enum value for each
/// workload type.
#[derive(Debug, Copy, Clone, Deserialize)]
#[serde(rename_all = "lowercase", tag = "type")]
pub enum Workload {
/// How to listen on ports.
Endpoints {
/// Governing the number of ports open.
#[serde(flatten)]
distribution: Distribution,
},

/// How to spawn processes.
Processes {
/// How often a new process will be spawn.
arrival_rate: f64,

/// How long processes are going to live.
departure_rate: f64,

/// Spawn a new process with random arguments.
random_process: bool,
},

/// How to invoke syscalls
Syscalls {
/// How often to invoke a syscall.
arrival_rate: f64,
},
}

/// Distribution for number of ports to listen on
#[derive(Debug, Copy, Clone, Deserialize)]
pub struct WorkloadConfig {
pub restart_interval: u64,
pub workload: Workload,
#[serde(tag = "distribution")]
pub enum Distribution {
/// Few processes are opening large number of ports, the rest are only few.
#[serde(alias = "zipf")]
Zipfian { n_ports: u64, exponent: f64 },

/// Every process opens more or less the same number of ports.
#[serde(alias = "uniform")]
Uniform { lower: u64, upper: u64 },
}

#[derive(Debug)]
pub enum WorkerError {}

impl Display for WorkerError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "worker error found")
}
}

/// Generic interface for workers of any type
pub trait Worker {
fn run_payload(&self) -> Result<(), WorkerError>;
}

/// General information for each worker, on which CPU is it running
/// and what is the process number.
#[derive(Debug, Copy, Clone)]
struct BaseConfig {
cpu: CoreId,
process: usize,
}

impl Display for BaseConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Process {} from {}", self.process, self.cpu.id)
}
}

#[cfg(test)]
Expand Down
15 changes: 15 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
//! Berserker workload generator.
//!
//! The implementation is covering two part:
//! * workload independent logic
//! * workload specific details
//!
//! Those have to be isolated as much as possible, and working together via
//! configuration data structures and worker interface.
//!
//! The execution contains following steps:
//! * Consume provided configuration
//! * For each available CPU core spawn specified number of worker processes
//! * Invoke a workload-specific logic via run_payload
//! * Wait for all the workers to finish
#[macro_use]
extern crate log;
extern crate core_affinity;
Expand Down
4 changes: 1 addition & 3 deletions src/worker/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ use std::{fmt::Display, net::TcpListener, thread, time};
use core_affinity::CoreId;
use log::info;

use crate::WorkloadConfig;

use super::{BaseConfig, Worker, WorkerError};
use crate::{BaseConfig, Worker, WorkerError, WorkloadConfig};

struct EndpointWorkload {
restart_interval: u64,
Expand Down
29 changes: 1 addition & 28 deletions src/worker/mod.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,15 @@
use std::fmt::Display;

use core_affinity::CoreId;
use rand::{thread_rng, Rng};
use rand_distr::{Uniform, Zipf};

use crate::{Distribution, Workload, WorkloadConfig};
use crate::{Distribution, Worker, Workload, WorkloadConfig};

use self::{endpoints::EndpointWorker, processes::ProcessesWorker, syscalls::SyscallsWorker};

pub mod endpoints;
pub mod processes;
pub mod syscalls;

#[derive(Debug)]
pub enum WorkerError {}

impl Display for WorkerError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "worker error found")
}
}

pub trait Worker {
fn run_payload(&self) -> Result<(), WorkerError>;
}

#[derive(Debug, Copy, Clone)]
struct BaseConfig {
cpu: CoreId,
process: usize,
}

impl Display for BaseConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Process {} from {}", self.process, self.cpu.id)
}
}

pub fn new_worker(
workload: WorkloadConfig,
cpu: CoreId,
Expand Down
6 changes: 2 additions & 4 deletions src/worker/processes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ use nix::{sys::wait::waitpid, unistd::Pid};
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use rand_distr::Exp;

use crate::{Workload, WorkloadConfig};

use super::{BaseConfig, Worker, WorkerError};
use crate::{BaseConfig, Worker, WorkerError, Workload, WorkloadConfig};

#[derive(Debug, Clone, Copy)]
pub struct ProcessesWorker {
Expand Down Expand Up @@ -67,7 +65,7 @@ impl ProcessesWorker {
}

impl Worker for ProcessesWorker {
fn run_payload(&self) -> Result<(), super::WorkerError> {
fn run_payload(&self) -> Result<(), WorkerError> {
info!("{self}");

let Workload::Processes {
Expand Down
6 changes: 2 additions & 4 deletions src/worker/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ use rand::{thread_rng, Rng};
use rand_distr::Exp;
use syscalls::{syscall, Sysno};

use crate::{Workload, WorkloadConfig};

use super::{BaseConfig, Worker};
use crate::{BaseConfig, Worker, WorkerError, Workload, WorkloadConfig};

#[derive(Debug, Copy, Clone)]
pub struct SyscallsWorker {
Expand Down Expand Up @@ -36,7 +34,7 @@ impl SyscallsWorker {
}

impl Worker for SyscallsWorker {
fn run_payload(&self) -> Result<(), super::WorkerError> {
fn run_payload(&self) -> Result<(), WorkerError> {
info!("{self}");

let Workload::Syscalls { arrival_rate } = self.workload.workload else {
Expand Down

0 comments on commit 73d8499

Please sign in to comment.