Rust implementations of the SPOT (Streaming Peaks Over Threshold) algorithm for real-time anomaly detection in time series data.
| Crate | Version | Documentation | License |
|---|---|---|---|
| libspot (C FFI) | |||
| libspot-rs (Pure Rust) |
Choose your preferred implementation:
# C FFI version (faster, requires C dependencies)
cargo add libspot
# Pure Rust version (safer, no dependencies)
cargo add libspot-rsBoth implementations provide the same core SPOT lifecycle API, so existing
fit/step integrations can switch crates by changing the import.
// Choose your implementation:
// use libspot::{SpotDetector, SpotConfig, SpotStatus}; // C FFI version
use libspot_rs::{SpotDetector, SpotConfig, SpotStatus}; // Pure Rust version
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create detector with default configuration
let config = SpotConfig::default();
let mut detector = SpotDetector::new(config)?;
// Fit with training data (normal distribution around 5.0)
let training_data: Vec<f64> = (0..1000)
.map(|i| 5.0 + (i as f64 * 0.01).sin() * 2.0)
.collect();
detector.fit(&training_data)?;
// Detect anomalies in real-time
let test_value = 50.0; // This should be an anomaly
match detector.step(test_value)? {
SpotStatus::Normal => println!("Normal data point"),
SpotStatus::Excess => println!("In the tail distribution"),
SpotStatus::Anomaly => println!("Anomaly detected! 🚨"),
}
Ok(())
}Both implementations support identical configuration:
use libspot_rs::SpotConfig; // or use libspot::SpotConfig;
let config = SpotConfig {
q: 0.0001, // Anomaly probability threshold (lower = more sensitive)
low_tail: false, // Monitor upper tail (set true for lower tail)
discard_anomalies: true, // Exclude anomalies from model updates
level: 0.998, // Quantile level that defines the tail
max_excess: 200, // Maximum number of excess values to store
};| Feature | libspot (C FFI) |
libspot-rs (Pure Rust) |
|---|---|---|
| Installation | cargo add libspot |
cargo add libspot-rs |
| Type | C FFI Bindings | Pure Rust Implementation |
| Core API | ✅ Reference API | ✅ Compatible |
| Performance | ~1.55 s (50M samples) | ~1.19 s (50M samples) |
| Memory Safety | ✅ Guaranteed | |
| Dependencies | 📦 C library + bindgen | 🎯 None |
| Cross-platform | ✅ Easy | |
| WebAssembly | ❌ Limited support | ✅ Full support |
| Results | Matches C 3.1.0 | Matches C 3.1.0 in consistency tests |
| Key Benefits | Fast, Proven, Compatible | Safe, Portable, WebAssembly |
| Documentation | docs.rs/libspot | docs.rs/libspot-rs |
libspot 3.1.0 bundles upstream C 3.1.0.
Both it and libspot-rs 0.4.0-rc.3 include the P² extrema marker fix from
upstream #42. Refitting models can
produce different thresholds and classifications than earlier versions.
CI compares C, Rust FFI, and pure Rust directly: anomaly/excess/normal counts
and thresholds must match to the printed precision. It then benchmarks all
three binaries on 50M samples. See the workflow run summaries
for current results and timings (Linux x86_64, release builds, hyperfine --warmup 1 --runs 5).
Benchmark Commands:
- Pure Rust:
cargo run -p libspot-rs -r --example basic_pure - C FFI:
cargo run -p libspot -r --example basic_ffi - Original C:
cd crates/libspot/libspot && make && cc -O3 -o /tmp/basic ../examples/basic.c dist/libspot.a.$(cat version) -Idist/ -lm && /tmp/basic
- API Documentation: docs.rs/libspot | docs.rs/libspot-rs
- Original C Library: asiffer/libspot
Contributions are welcome! Please feel free to submit issues and pull requests.
The repository is a Cargo workspace with three members:
libspot: the C FFI wrapper and its tests.libspot-rs: the pure Rust implementation and its tests.libspot-compat-tests: cross-implementation tests and comparison examples; this package is not published.
All members share the root Cargo.lock and target/ directory. From the
repository root, run:
# Run tests for every workspace member (also the default for cargo test here).
cargo test --workspace --locked
# Run one package, including pure Rust without its default features.
cargo test -p libspot-rs --no-default-features --locked
cargo test -p libspot-compat-tests --locked
# Check all members and run a comparison example.
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
cargo run -p libspot-compat-tests --release --example compare_implementations --lockedThis project is licensed under the GNU Lesser General Public License v3.0 (LGPL-3.0) to comply with the underlying libspot C library license.
The logo design is adapted from the original libspot logo with Rust-themed styling to reflect this project's implementation in the Rust programming language.