lockfree-object-pool 0.1.2

A thread-safe object pool collection with automatic return and attach/detach semantics.
Documentation

Lock Free Object Pool

License Cargo Documentation CI

A thread-safe object pool collection with automatic return.

Some implementations are lockfree :

  • LinearObjectPool
  • SpinLockObjectPool

Other use std::Mutex :

  • MutexObjectPool

And NoneObjectPool basic allocation without pool.

Usage

[dependencies]
lockfree-object-pool = "0.1"
extern crate lockfree_object_pool;

Example

The general pool creation looks like this for

 let pool = LinearObjectPool::<u32>::new(
     ||  Default::default(), 
     |v| {*v = 0; });

And use the object pool

  let mut item = pool.pull();
  *item = 5;
  ...  

At the end of the scope item return in object pool.

Interface

All implementations support same interface :

struct ObjectPool<T> {  
}

impl<T> ObjectPool<T> {
  // for LinearObjectPool, SpinLockObjectPool and MutexObjectPool
  // init closure used to create an element
  // reset closure used to reset element a dropped element
  pub fn new<R, I>(init: I, reset: R) -> Self
    where
        R: Fn(&mut T) + 'static,
        I: Fn() -> T + 'static + Clone,
    {
      ...
    }

  // for NoneObjectPool
  // init closure used to create an element
  pub fn new<I>(init: I) -> Self
    where
        I: Fn() -> T + 'static
    {
      ...
    }

  pub fn pull(&self) -> Reusable<T> {
    ...
  }
}

struct Reusable<T> {  
}

impl<'a, T> DerefMut for Reusable<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        ...
    }
}

impl<'a, T> Deref for MutexReusable<'a, T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        ...
    }
}

Multithreading

All implementation support allocation/desallocation from on or more thread. You only need to wrap the pool in a [std::sync::Arc] :

 let pool = Arc::new(LinearObjectPool::<u32>::new(
     ||  Default::default(), 
     |v| {*v = 0; }));

Performance

Global report.

Allocation

ObjectPool Duration in Monothreading (us) Duration Multithreading (us)
NoneObjectPool 1.2162 0.63033
MutexObjectPool 1.2458 1.5140
SpinLockObjectPool 1.2437 1.3737
LinearObjectPool 0.21764 0.22418
crate 'sharded-slab' 1.5 0.82790
crate 'object-pool' 0.61956 0.26323

Report monothreading and multithreading.

Desallocation

ObjectPool Duration in Monothreading (ns) Duration Multithreading (ns)
NoneObjectPool 91.362 86.530
MutexObjectPool 25.486 101.40
SpinLockObjectPool 22.089 50.411
LinearObjectPool 7.1384 34.481
crate 'sharded-slab' 9.0273 11.127
crate 'object-pool' 20.038 47.768

Report monothreading and multithreading.

Comparison with Similar Crates

  • crate 'sharded-slab': I like pull interface but i dislike

    • Default / Reset trait because not enough flexible
    • Performance
  • crate 'object-pool': use a spinlock to sync and the performance are pretty good but i dislike :

    • need to specify fallback at each pull call :
    use object_pool::Pool;
    let pool = Pool::<Vec<u8>>::new(32, || Vec::with_capacity(4096);
    // ...
    let item1 = pool.pull(|| Vec::with_capacity(4096));
    // ...
    let item2 = pool.pull(|| Vec::with_capacity(4096));
    
    • no reset mechanism, need to do manually

TODO

Implementation detail

TODO

Licence

cf Boost Licence

Related Projects