lifeguard

Object Pool Manager

API Documentation

Examples

Pool issues owned values wrapped in smartpointers.

```rust extern crate lifeguard; use lifeguard::*;

fn main() { let mut pool : Pool = pool().with(StartingSize(10)).build(); { let string = pool.new_from("Hello, World!"); // Pool size is now 9 } // Values that have gone out of scope are automatically moved back into the pool. // Pool size is 10 again } ```

Values taken from the pool can be dereferenced to access/mutate their contents.

```rust extern crate lifeguard; use lifeguard::*;

fn main() { let mut pool : Pool = pool().with(StartingSize(10)).build(); let mut string = pool.newfrom("cat"); string.pushstr("s love eating mice"); //string.asmut() also works asserteq!("cats love eating mice", *string); } ```

Values can be unwrapped, detaching them from the pool.

```rust extern crate lifeguard; use lifeguard::*;

fn main() { let mut pool : Pool = pool().with(StartingSize(10)).build(); { let string : String = pool.new().detach(); } // The String goes out of scope and is dropped; it is not returned to the pool assert_eq!(9, pool.size()); } ```

Values can be manually entered into / returned to the pool.

```rust extern crate lifeguard; use lifeguard::*;

fn main() { let mut pool : Pool = pool().with(StartingSize(10)).build(); { let string : String = pool.detached(); // An unwrapped String, detached from the Pool asserteq!(9, pool.size()); let rstring : Recycled = pool.attach(string); // The String is attached to the pool again asserteq!(9, pool.size()); // but it is still checked out from the pool } // rstring goes out of scope and is added back to the pool assert_eq!(10, pool.size()); } ```

Pool's builder API can be used to customize the behavior of the pool.

```rust extern crate lifeguard; use lifeguard::*;

fn main() { let mut pool : Pool = pool() // The pool will allocate 128 values for immediate use. More will be allocated on demand. .with(StartingSize(128)) // The pool will only grow up to 4096 values. Further values will be dropped. .with(MaxSize(4096)) // The pool will use this closure (or other object implementing Supply) to allocate .with(Supplier(|| String::with_capacity(1024))) .build(); // ... } ```

Highly Unscientific Benchmarks

Benchmark source can be found here. Tests were run on a VirtualBox VM with 3 CPUs @ 3Ghz and 4GB of RAM.

Uninitialized Allocation

| String::with_capacity | Pool::new_rc | Improvement | Pool::new | Improvement | |:----------------------------:|:--------------------------:|:-----------:|:--------------------------:|:-----------:| | 1421183 ns/iter (+/- 161572) | 841286 ns/iter (+/- 78602) | ~40.80% | 615875 ns/iter (+/- 53906) | ~56.67% |

Initialized Allocation

| String::to_owned | Pool::new_rc_from | Improvement | Pool::new_from | Improvement | |:----------------------------:|:---------------------------:|:-----------:|:----------------------------:|:-----------:| | 2256492 ns/iter (+/- 184229) | 1652247 ns/iter (+/- 185096)| ~26.78% | 1430212 ns/iter (+/- 146108) | ~36.62% |

Vec<Vec<String>> Allocation

Adapted from this benchmark.

| Vec::new + String::to_owned | Pool::new_rc + Pool::new_rc_from | Improvement | Pool::new + Pool::new_from| Improvement | |:-------------------------------:|:------------------------------------:|:-----------:|:------------------------------:|:-----------:| | 1303594 ns/iter (+/- 98974) | 723338 ns/iter (+/- 82782) | ~44.51% | 678324 ns/iter (+/- 88772) | ~47.97% |

Ideas and PRs welcome!

Inspired by frankmcsherry's recycler.