Skip to content

Commit

Permalink
Small cosmetic improvements:
Browse files Browse the repository at this point in the history
* Added feature flags for better integration
* Solved Clippy Warnings for Rust 1.83
* Fixed formatting issues
  • Loading branch information
zertyz committed Jan 9, 2025
1 parent e29e04e commit 8175390
Show file tree
Hide file tree
Showing 17 changed files with 206 additions and 165 deletions.
38 changes: 28 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,46 @@ repository = "https://github.com/zertyz/big-o"
documentation = "https://docs.rs/big-o-test/"
license = "Unlicense"

[features]
default = [
"report_stdout", # Shows the algorithm analysis report for each test -- sending to stdout. Use `no_report` if you don't want it or `report_stderr` to leave stdout alone
"tolerance_10_percent", # Accepts measurement discrepancies of up to 10% -- for machines not performing any other work other than running the tests
]

# Report generation options
report_stdout = [] # Shows the algorithm analysis report for each test -- sending to stdout
report_stderr = [] # Shows the algorithm analysis report for each test -- sending to stderr
no_report = [] # Don't mess with nither stderr nor stdout -- do not show any report.
# -- the same behavior as not specifying neither `report_stdout` nor `report_stderr`.

# Measurement tolerance options
tolerance_10_percent = [] # Accepts measurement discrepancies of up to 10% -- for machines not performing any other work other than running the tests
# -- this behavior is the default if no `tollerance_*_percent` feature is specifyed
tolerance_25_percent = [] # Accepts measurement discrepancies of up to 25% -- for machines running other tasks along with the tests

# Misc
no_allocator_metrics = [] # If you don't want to change the global allocator (injecting our metrics probe in it), use this feature
# -- however, there will be no SPACE analysis


[workspace]


[dependencies]
crossbeam = "0.8" # scoped threads
keen-retry = "0.4" # for automatic retries on flaky execution passes
crossbeam = "0.8" # scoped threads
keen-retry = "0.5" # for automatic retries on flaky execution passes


[dev-dependencies] # dev dependencies should become normal dependencies when building docs for tests
ctor = "0.2" # initializer functions -- that run before main
serial_test = "2.0" # run tests serially
parking_lot = "0.12" # way faster than std mutex
spin_sleep = "1.1" # precise sleeping, avoiding busy loops on some tests
rand = "0.8" # used by some tests to avoid call cancellation optimizations when running in release mode


[features]
serial_test = "3" # run tests serially
parking_lot = "0.12" # way faster than std mutex
spin_sleep = "1.1" # precise sleeping, avoiding busy loops on some tests
rand = "0.8" # used by some tests to avoid call cancellation optimizations when running in release mode


[package.metadata.docs.rs]
rustdoc-args = ["--document-private-items"] # enables full documentation (including test modules and test cases)
rustdoc-args = ["--cfg", "test", "--document-private-items"] # enables full documentation (including test modules and test cases)


# DOCUMENTATION
Expand Down
45 changes: 0 additions & 45 deletions src/configs.rs

This file was deleted.

61 changes: 61 additions & 0 deletions src/features.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//! Contains code for handling the Cargo features used to compile this crate.
#![allow(dead_code)]

use std::io::{stdout,stderr,Write};
use crate::metrics_allocator::MetricsAllocator;

#[cfg(any(feature = "tolerance_10_percent", not(any(feature = "tolerance_25_percent"))))]
/// acceptable proportional variance (acceptable measurement errors) when analysing algorithm's time & space complexities
pub const PERCENT_TOLERANCE: f64 = 0.10;

#[cfg(feature = "tolerance_25_percent")]
/// acceptable proportional variance (acceptable measurement errors) when analysing algorithm's time & space complexities
pub const PERCENT_TOLERANCE: f64 = 0.25;

#[cfg(feature = "report_stdout")]
/// Function to output an `&str` -- used to sink analysis reports -- controlled by the crate's features (stdout, stderr, no_output)
pub const OUTPUT: fn(&str) = stdout_write;

#[cfg(feature = "report_stderr")]
/// Function to output an `&str` -- used to sink analysis reports -- controlled by the crate's features (stdout, stderr, no_output)
pub const OUTPUT: fn(&str) = stderr_write;

#[cfg(not(any(feature = "report_stdout", feature = "report_stderr")))]
/// Function to output an `&str` -- used to sink analysis reports -- controlled by the crate's features (stdout, stderr, no_output)
pub const OUTPUT: fn(&str) = null_write;

#[cfg(not(feature = "no_allocator_metrics"))]
#[global_allocator]
/// Allows access to the metrics allocator -- replacing the Global Allocator for tests
/// (provided this crate is used as `dev-dependency`).
/// NOTE: as mentioned in the README, if you want ot use this crate in integration tests, you should
/// have a feature in your project to only include this crate if you are compiling for integration tests
pub static ALLOC: MetricsAllocator<SAVE_POINT_RING_BUFFER_SIZE> = MetricsAllocator::new();

/// Regarding the [MetricsAllocator] used for space complexity analysis, this property specifies the maximum number of "save points"
/// that might be in use at the same time
pub const SAVE_POINT_RING_BUFFER_SIZE: usize = 1024;


fn stdout_write(buf: &str) {
sync_outputs();
print!("{}", buf);
sync_outputs();
}

fn stderr_write(buf: &str) {
sync_outputs();
eprint!("{}", buf);
sync_outputs();
}

/// Flushes both stdout and stderr so the next output will be in sync with everything that came before
fn sync_outputs() {
_ = stdout().flush();
_ = stderr().flush();
}

fn null_write(_buf: &str) {
// release compilations will optimize out this call for '_buf' is not used
}

6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#![doc = include_str!("../README.md")]


pub mod runners;
pub mod low_level_analysis;
pub mod metrics_allocator;
pub mod configs;

mod features;

// exported symbols
pub use {
configs::{ALLOC, OUTPUT},
features::{ALLOC, OUTPUT},
low_level_analysis::types::{
BigOAlgorithmComplexity,
TimeUnits,
Expand Down
2 changes: 1 addition & 1 deletion src/low_level_analysis/configs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! configurations for this sub-module, with definitions delegated to the [crate::configs] module
pub use crate::configs::{
pub use crate::features::{
PERCENT_TOLERANCE,
ALLOC,
};
8 changes: 4 additions & 4 deletions src/low_level_analysis/low_level_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,14 @@ pub fn analyse_set_resizing_iterator_complexity(u1: f64, u2: f64, n: f64) -> Big
}


#[cfg(any(test, feature="dox"))]
#[cfg(test)]
mod tests {

//! Unit tests for [low_level_analysis](super) module -- using 'serial_test' crate in order to make time measurements more reliable.
use super::*;
use crate::{
configs::{OUTPUT},
features::{OUTPUT},
low_level_analysis::{
types::{
BigOIteratorAlgorithmType,
Expand Down Expand Up @@ -137,7 +137,7 @@ mod tests {


/// tests time & space complexity analysis on real constant set algorithms
#[cfg_attr(not(feature = "dox"), test)]
#[test]
#[serial]
fn analyse_constant_set_algorithm_real_test() {

Expand Down Expand Up @@ -248,7 +248,7 @@ mod tests {
}

/// tests time & space complexity analysis on real set resizing algorithms
#[cfg_attr(not(feature = "dox"), test)]
#[test]
#[serial]
fn analyse_set_resizing_algorithm_real_test() {

Expand Down
4 changes: 3 additions & 1 deletion src/low_level_analysis/space_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub fn analyse_space_complexity(passes_info: &AlgorithmPassesInfo,
/// - O(1) for functions that do not use ram at all (or that use a const amount, regardless of the set size), like uncached reads / updates
/// - O(log(n)) for recursive binary searches and the like
/// - O(n) if caching takes place for reads / updates
///
/// See [analyse_space_complexity_for_set_resizing_iterator_algorithm()] for iterator algorithms that resize the data set they operate on.
pub fn analyse_space_complexity_for_constant_set_iterator_algorithm(passes_info: &ConstantSetIteratorAlgorithmPassesInfo,
measurements: &BigOSpaceMeasurements) -> BigOAlgorithmComplexity {
Expand All @@ -56,6 +57,7 @@ pub fn analyse_space_complexity_for_constant_set_iterator_algorithm(passes_info:
/// binary tree for the vector elements -- to allow fast searches while keeping the traversal order (to match insertion order)
/// - O(n) for wired algorithms where each new inserted (n+1) element cause another (n) or even (n+1) elements to be insert as well.
/// Example: increment by 1 both chess board dimensions. board(n) will become board(n+1): 1+2*n elements are added. O(n) memory consumption.
///
/// See [analyse_space_complexity_for_constant_set_iterator_algorithm()] for non-iterator algorithms and for iterator algorithms that operate on a constant set.
pub fn analyse_space_complexity_for_set_resizing_iterator_algorithm(passes_info: &SetResizingIteratorAlgorithmPassesInfo,
measurements: &BigOSpaceMeasurements) -> BigOAlgorithmComplexity {
Expand All @@ -69,7 +71,7 @@ pub fn analyse_space_complexity_for_set_resizing_iterator_algorithm(passes_info:
analyse_set_resizing_iterator_complexity(s1, s2, n)
}

#[cfg(any(test, feature="dox"))]
#[cfg(test)]
mod tests {

//! Unit tests for [space_analysis](super) module
Expand Down
4 changes: 2 additions & 2 deletions src/low_level_analysis/time_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ pub fn analyse_time_complexity_for_set_resizing_iterator_algorithm<ScalarTimeUni
analyse_set_resizing_iterator_complexity(t1, t2, n)
}

#[cfg(any(test, feature="dox"))]
#[cfg(test)]
mod tests {

//! Unit tests for [time_analysis](super) module
use super::*;
use crate::configs::*;
use crate::features::*;
use serial_test::serial;


Expand Down
3 changes: 2 additions & 1 deletion src/low_level_analysis/types/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,14 @@ pub struct BigOTimePassMeasurements<'a, ScalarTimeUnit> where ScalarTimeUnit: Cl
}

/// represents an algorithm's execution memory usage measurements for passes 1 & 2 -- in bytes
#[derive(Default)]
pub struct BigOSpaceMeasurements {
pub pass_1_measurements: BigOSpacePassMeasurements,
pub pass_2_measurements: BigOSpacePassMeasurements,
}

/// memory usage measurements, in bytes, for a pass execution
#[derive(Debug,Clone,Copy)]
#[derive(Debug,Clone,Copy,Default)]
pub struct BigOSpacePassMeasurements {
/// heap memory in use just before starting the pass execution
pub used_memory_before: usize,
Expand Down
31 changes: 8 additions & 23 deletions src/low_level_analysis/types/types_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ impl<T: BigOAlgorithmMeasurements> Display for BigOAlgorithmAnalysis<T> {
}


impl<'a, ScalarTimeUnit: Copy> BigOAlgorithmMeasurements for AlgorithmMeasurements<'a, ScalarTimeUnit> {
impl<ScalarTimeUnit: Copy> BigOAlgorithmMeasurements for AlgorithmMeasurements<'_, ScalarTimeUnit> {
fn space_measurements(&self) -> &BigOSpaceMeasurements {
&self.space_measurements
}
}
impl<'a, ScalarTimeUnit: Copy> Display for AlgorithmMeasurements<'a, ScalarTimeUnit> {
impl<ScalarTimeUnit: Copy> Display for AlgorithmMeasurements<'_, ScalarTimeUnit> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let pass_1_time = format!("{}", self.time_measurements.pass_1_measurements);
let pass_2_time = format!("{}", self.time_measurements.pass_2_measurements);
Expand All @@ -92,12 +92,12 @@ impl<'a, ScalarTimeUnit: Copy> Display for AlgorithmMeasurements<'a, ScalarTimeU
}


impl<'a, ScalarTimeUnit: Copy> BigOAlgorithmMeasurements for ConstantSetIteratorAlgorithmMeasurements<'a, ScalarTimeUnit> {
impl<ScalarTimeUnit: Copy> BigOAlgorithmMeasurements for ConstantSetIteratorAlgorithmMeasurements<'_, ScalarTimeUnit> {
fn space_measurements(&self) -> &BigOSpaceMeasurements {
&self.space_measurements
}
}
impl<'a, ScalarTimeUnit: Copy> Display for ConstantSetIteratorAlgorithmMeasurements<'a, ScalarTimeUnit> {
impl<ScalarTimeUnit: Copy> Display for ConstantSetIteratorAlgorithmMeasurements<'_, ScalarTimeUnit> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let pass_1_time = format!("{}", self.time_measurements.pass_1_measurements);
let pass_2_time = format!("{}", self.time_measurements.pass_2_measurements);
Expand All @@ -120,12 +120,12 @@ impl<'a, ScalarTimeUnit: Copy> Display for ConstantSetIteratorAlgorithmMeasureme
}


impl<'a,ScalarTimeUnit: Copy> BigOAlgorithmMeasurements for SetResizingIteratorAlgorithmMeasurements<'a,ScalarTimeUnit> {
impl<ScalarTimeUnit: Copy> BigOAlgorithmMeasurements for SetResizingIteratorAlgorithmMeasurements<'_, ScalarTimeUnit> {
fn space_measurements(&self) -> &BigOSpaceMeasurements {
&self.space_measurements
}
}
impl<'a,ScalarTimeUnit: Copy> Display for SetResizingIteratorAlgorithmMeasurements<'a,ScalarTimeUnit> {
impl<ScalarTimeUnit: Copy> Display for SetResizingIteratorAlgorithmMeasurements<'_, ScalarTimeUnit> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let pass_1_time = format!("{}", self.time_measurements.pass_1_measurements);
let pass_2_time = format!("{}", self.time_measurements.pass_2_measurements);
Expand Down Expand Up @@ -163,11 +163,6 @@ impl BigOSpaceMeasurements {
self.pass_1_measurements.max_used_memory - std::cmp::max(self.pass_1_measurements.used_memory_after, self.pass_1_measurements.used_memory_before)
}
}
impl Default for BigOSpaceMeasurements {
fn default() -> Self {
Self { pass_1_measurements: BigOSpacePassMeasurements::default(), pass_2_measurements: BigOSpacePassMeasurements::default() }
}
}
impl Display for BigOSpaceMeasurements {
// shows allocated / deallocated amount + any used auxiliary space
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Expand Down Expand Up @@ -215,16 +210,6 @@ impl Display for BigOSpacePassMeasurements {
write!(f, "{}", self.fmt_over_n(1))
}
}
impl Default for BigOSpacePassMeasurements {
fn default() -> Self {
Self {
used_memory_before: 0,
used_memory_after: 0,
max_used_memory: 0,
min_used_memory: 0,
}
}
}


impl<T> Default for TimeUnit<T> {
Expand All @@ -234,7 +219,7 @@ impl<T> Default for TimeUnit<T> {
}


#[cfg(any(test, feature="dox"))]
#[cfg(test)]
mod tests {

//! Unit tests for [types_impl](super) submodule -- using 'serial_test' crate in order to make time measurements more reliable.
Expand All @@ -250,7 +235,7 @@ mod tests {

/// assures serializations & implementors of *Display* from [types] work without panics
/// -- also outputs them for manual inspection
#[cfg_attr(not(feature = "dox"), test)]
#[test]
#[serial]
fn serialization() {
println!("BigOAlgorithmComplexity enum members, as strings:");
Expand Down
Loading

0 comments on commit 8175390

Please sign in to comment.