recycler

A small Rust library for recycling types with owned memory

Recycler provides the Recycler trait and several implementations. Each Recycler object is capable of "recycling" items of its associated type Item.

rust // allows recycling of items pub trait Recycler : Default { type Item; fn recycle(&mut self, _item: Self::Item) { } }

The intended behavior is that types with owned memory will be deconstructed and have the owned memory enqueued. For example, the implementation for VecRecycler<R> is just

rust // recycles vec contents, then stashes the vec impl<R: Recycler> Recycler for VecRecycler<R> { type Item = Vec<R::Item>; fn recycle(&mut self, mut vec: Vec<R::Item>) { while let Some(x) = vec.pop() { self.recycler.recycle(x) } self.stash.push(vec); } }

While recycling might sound great just because of civic duty, the real purpose is that these recyclers are able to return the owned memory to you, using a pattern not unlike standard allocation. Where you might write something like

```rust

[bench]

fn allocatevecvecstr(bencher: &mut Bencher) { bencher.iter(|| { let mut v1 = Vec::new(); for _ in 0..10 { let mut v2 = Vec::new(); for _ in 0..10 { v2.push(("test!").toowned()); } v1.push(v2); } v1 }); } ```

you can now instead write something pretty similar (no, not the same):

```rust

[bench]

fn recyclervecvecstr(bencher: &mut Bencher) { let mut r1: VecRecycler> = Default::default(); bencher.iter(|| { let v = { let (mut v1, r2) = r1.new(); for _ in 0..10 { let (mut v2, r3) = r2.new(); for _ in 0..10 { v2.push(r3.newfrom("test!")); } v1.push(v2); } v1 }; r1.recycle(v); }); } ```

There is a bit of nonsense because of lexical borrows, and because type inference doesn't seem to do a great job finding an implementation with an associated type as a constraint. Perhaps I'll learn that this was a bad pattern.

The reason you do this is because if you run those benchmarks up there, you see numbers like:

test allocate_vec_vec_str   ... bench:      4556 ns/iter (+/- 2166)
test recycler_vec_vec_str   ... bench:      2033 ns/iter (+/- 945)

If you do less formatting stuff and just put some u64 data in the vectors, you see an even bigger distinction:

test allocate_vec_vec_u64   ... bench:      1281 ns/iter (+/- 303)
test recycler_vec_vec_u64   ... bench:       154 ns/iter (+/- 27)

The main down side I can think of is that you are getting vectors that may have more memory than you need. They may also live for a while in the recycler. I almost added a clear method, but if you want to do that just make a new recycler and clobber the old one.

If anyone has any hot tips or recommendations, especially about a macro or syntax extension that would let structs and such automatically derive recyclers, I'd be all ears. Any other friendly comments or contributions are also welcome.