Crate strider [−] [src]
useful for stepping (variable step) a window (variable size) through a streaming (possibly infinite) series of values while avoiding unnecessary memory allocations
essential in computing the short-time fourier transform and other data/signal processing methods.
to use add strider = "0.1.1"
to the [dependencies]
section of your Cargo.toml
and call extern crate strider;
in your code.
example
following is a program that reads a stream of chars from stdin.
it writes every consecutive sequence of WINDOW_SIZE
chars that
is STEP_SIZE
apart to stdout.
for the input of ABCDEFGHIJK
it produces the output ABCDCDEFEFGHGHIJ
.
it uses constant memory and does no allocations after the initial ones.
you should be able to grasp the idea and adapt it to your needs.
use std::io; use std::io::{Write, Read}; extern crate strider; use strider::{SliceRing, SliceRingImpl}; fn main() { const WINDOW_SIZE: usize = 4; const STEP_SIZE: usize = 2; let mut ring = SliceRingImpl::<u8>::new(); let mut input_buffer: &mut [u8] = &mut [0; 20]; let mut window_buffer: &mut [u8] = &mut [0; WINDOW_SIZE]; loop { let input_count = io::stdin().read(input_buffer).unwrap(); // leave the loop when we reach end of file if input_count == 0 { break; } // add elements to the back of the ring ring.push_many_back(&input_buffer[..input_count]); // read as long as we can read windows of length `WINDOW_SIZE` while WINDOW_SIZE <= ring.len() { ring.read_many_front(window_buffer); io::stdout().write(window_buffer).unwrap(); // do a step by dropping the first `STEP_SIZE` elements in ring ring.drop_many_front(STEP_SIZE); } } }
overview
memory
these operations read from and writes to buffers that you control.
performance
strider::SliceRing
is implemented by std::collections::VecDeque
and strider::SliceRingImpl
.
strider::SliceRingImpl
is an optimized implementation
of strider::SliceRing
that is 2 to 6 times faster than
the implementation using std::collections::VecDeque
.
see the benchmarks.
two backing buffer types: one simple for illustration one optimized for performance benchmarked against each other
often you want to do deque operations on multiple values at once. operations implemented on std::collections::VecDeque as well as an optimized implementation.
windowing the equivalent of 1 minute of 44100 hz audio samples with a window_size of 1024 and step_size of 512 only takes a few (6) milliseconds and constant memory of about
this is probably what you want
sliding-window uses a std::collections::VecDeque
under the hood.
will double in size only when full.
for the common case this allocates memory once, maybe twice and is done with it.
fast
performance
optimized for and restricted to working on multiple things at once. which it can do faster.
performance is relative. so instead of claiming that this is fast, we'll instead prove
that it is much faster than a naive implementation building on std::collections::VecDeque
.
reads integers from stdin and without any memory allocations (past the initial).
Macros
test_slice_ring! |
macro containing a test run that is used to test and benchmark
different implementations of the |
Structs
SliceRingImpl |
readable area starts at |
Traits
SliceRing |
ringbuffer operations on slices |