Quick Pool: High Performance Rust Async Resource Pool

Overview

Quick Pool

High Performance Rust Async Resource Pool

Crates.io Docs.rs Rust Rust GitHub Workflow Crates.io License

Usage

DBCP

Database Backend Adapter Version
PostgreSQL tokio-postgres qp-postgres qp-postgres-version

Example

use async_trait::async_trait;
use qp::pool::{self, Pool};
use qp::resource::Factory;
use std::convert::Infallible;

pub struct IntFactory;

#[async_trait]
impl Factory for IntFactory {
    type Output = i32;
    type Error = Infallible;

    async fn try_create(&self) -> Result<Self::Output, Self::Error> {
        Ok(0)
    }

    async fn validate(&self, resource: &Self::Output) -> bool {
        resource >= &0
    }
}

#[tokio::main]
async fn main() {
    let pool = Pool::new(IntFactory, 1); // max_size=1

    // create a resource when the pool is empty or all resources are occupied.
    let mut int = pool.acquire().await.unwrap();
    *int = 1;
    dbg!(*int); // 1
    dbg!(int.is_valid().await); // true; validate the resource.

    // release the resource and put it back to the pool.
    drop(int);

    let mut int = pool.acquire().await.unwrap();
    dbg!(*int); // 1
    *int = 100;
    drop(int);

    let mut int = pool.acquire().await.unwrap();
    dbg!(*int); // 100
    *int = -1; // the resource will be disposed because `validate` is false.
    dbg!(int.is_valid().await); // false
    drop(int);

    let int = pool.acquire_unchecked().await.unwrap();
    dbg!(*int); // -1; no validation before acquiring.
    drop(int);

    let int = pool.acquire().await.unwrap();
    dbg!(*int); // 0; old resource is disposed and create new one.

    // take the resource from the pool.
    let raw_int: i32 = pool::take_resource(int); // raw resource
    dbg!(raw_int); // 0
    drop(raw_int);

    let _int = pool.acquire().await.unwrap();
    // `_int` will be auto released by `Pooled` destructor.
}

Alternatives

Crate Async Runtime Version
bb8 tokio bb8-version
deadpool async-std, tokio deadpool-version
mobc actix, async-std, tokio mobc-version
r2d2 not supported r2d2-version

Performance Comparison

total
bb8 deadpool
mobc qp
r2d2

Benchmarked on GitHub Action: Ubuntu 20.04, CPU 2 Core, RAM 7GB

For more information, see Quick Pool Benchmark.

License

Copyright (c) 2021 Seungjae Park

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Quick Pool is licensed under the MIT License.

You might also like...
A high-performance storage engine for modern hardware and platforms.

PhotonDB A high-performance storage engine for modern hardware and platforms. PhotonDB is designed from scratch to leverage the power of modern multi-

A generic connection pool for Rust

r2d2 A generic connection pool for Rust. Documentation Opening a new database connection every time one is needed is both inefficient and can lead to

Skytable rust client support library for the bb8 connection pool

bb8-skytable Skytable rust client support library for the bb8 connection pool. Heavily based on bb8-redis Basic usage example use bb8_skytable::{

rust-mysql-simple support library for the r2d2 connection pool

r2d2-mysql rust-mysql-simple support library for the r2d2 connection pool.

Memcached support for the r2d2 connection pool (Rust)

Memcached support for the r2d2 connection pool (Rust)

rust-postgres support library for the r2d2 connection pool

r2d2-postgres Documentation rust-postgres support library for the r2d2 connection pool. Example use std::thread; use r2d2_postgres::{postgres::NoTls,

LDAP support for the r2d2 connection pool

r2d2-ldap LDAP support for the r2d2 connection pool Install Add this to your Cargo.toml: [dependencies] r2d2-ldap = "0.1.1" Basic Usage use std::threa

Oracle support for the r2d2 connection pool

r2d2-oracle The documentation can be found on docs.rs. Oracle support for the r2d2 connection pool. This fits in between the r2d2 connection manager a

ODBC adapter for r2d2 connection pool

ODBC adapter for r2d2 connection pool

Comments
  • Add tests for aborted Pool::acquire and Semaphore::acquire calls showing a memory leak

    Add tests for aborted Pool::acquire and Semaphore::acquire calls showing a memory leak

    I wanted to show the reason for the deadlock I reported in #2 but found a memory leak instead.

    A aborted Semaphore::acquire does leave the waker behind in the queue which causes the memory to grow indefinitely.

    The thing I don't understand: I wanted to show that the aborted task A leaves a waker for itself in the queue and when the permit is returned task A is woken instead of task B thus causing the code to deadlock. This does not happen. Instead I found that calling waker.wake() for task A actually wakes task B.

    I'm trying to wrap my head around why it works that way and doesn't deadlock. Whatever the reason for that behavior is. It's a memory leak nonetheless.

    bug enhancement 
    opened by bikeshedder 2
  • qp deadlocks in Astro36/rust-pool-benchmark

    qp deadlocks in Astro36/rust-pool-benchmark

    I haven't been able to figure out what's wrong with it but I'm curious why that's happening:

    • Astro36/rust-pool-benchmark#1

    I'm opening this as I'm currently evaluating the possibility of going back to a crossbeam based implementation in deadpool. I only switched to a Mutex<VecDeque> in 0.7 as I saw a neglectable performance impact back then. It also made features like resizable pools trivial.

    I've looked at your Semaphore implementation and the one from async-lock. I gave both a try and either one performs better than the one from tokio. I'm just very hesitant to switch until we figure out why the benchmark deadlocks.

    Using a different Semaphore implementation and crossbeam-queue yields a performance improvement of 2x-3x which is quite amazing and worth exploring.


    I also opened an issue in the bb8 issue tracker, but since it has a completely different implementation and doesn't even use semaphores I don't think those problems are related in any way:

    • djc/bb8#122

    I just hope it's not an error in the benchmark implementation and I've opened those two issues in error. :see_no_evil:

    bug help wanted good first issue 
    opened by bikeshedder 0
Releases(qp-v-0.2.1)
  • qp-v-0.2.1(Jun 12, 2022)

    v0.2.0

    Released June 12, 2022

    Fixed

    • Fix memory leak when canceling async acquire on semaphore and add some test cases: #3

    Thanks to @bikeshedder

    Source code(tar.gz)
    Source code(zip)
  • qp-postgres-v0.1.1(Jan 9, 2022)

  • qp-v0.2.0(Jan 8, 2022)

    v0.2.0

    Released Jan 8, 2022

    Added

    • Add Pool::reserve function.

    Changed

    • API breaking changes:
      • qp::pool::Pool -> qp::Pool
      • qp::pool::Pooled -> qp::Pooled
      • Pooled function names changed.
      • qp::resource::Factory -> qp::resource::Manage
      • Manage::Error type changed.

    Removed

    • Remove tokio-semaphore feature.
    • Remove error module.
    Source code(tar.gz)
    Source code(zip)
  • qp-v0.1.3(Dec 22, 2021)

  • qp-v0.1.2(Dec 9, 2021)

  • qp-v0.1.1(Dec 7, 2021)

  • qp-postgres-v0.1.0(Dec 6, 2021)

  • qp-v0.1.0(Dec 1, 2021)

Owner
Seungjae Park
Interested in NLP and Machine Learning.
Seungjae Park
An async executor based on the Win32 thread pool API

wae An async executor based on the Win32 thread pool API use futures::channel::oneshot; #[wae::main] async fn main() { let (tx, rx) = oneshot::ch

Raphaël Thériault 10 Dec 10, 2021
Cassandra DB native client written in Rust language. Find 1.x versions on https://github.com/AlexPikalov/cdrs/tree/v.1.x Looking for an async version? - Check WIP https://github.com/AlexPikalov/cdrs-async

CDRS CDRS is looking for maintainers CDRS is Apache Cassandra driver written in pure Rust. ?? Looking for an async version? async-std https://github.c

Alex Pikalov 338 Jan 1, 2023
📺 Netflix in Rust/ React-TS/ NextJS, Actix-Web, Async Apollo-GraphQl, Cassandra/ ScyllaDB, Async SQLx, Kafka, Redis, Tokio, Actix, Elasticsearch, Influxdb Iox, Tensorflow, AWS

Fullstack Movie Streaming Platform ?? Netflix in RUST/ NextJS, Actix-Web, Async Apollo-GraphQl, Cassandra/ ScyllaDB, Async SQLx, Spark, Kafka, Redis,

null 34 Apr 17, 2023
High-level async Cassandra client written in 100% Rust.

CDRS tokio CDRS is production-ready Apache Cassandra driver written in pure Rust. Focuses on providing high level of configurability to suit most use

Kamil Rojewski 73 Dec 26, 2022
A prototype of a high-performance KV database built with Rust.

async-redis A prototype of a high-performance KV database built with Rust. Author: 3andero 11/10/2021 Overview The project starts as a fork of mini-re

null 3 Nov 29, 2022
Rust High Performance compile-time ORM(RBSON based)

WebSite | 简体中文 | Showcase | 案例 A highly Performant,Safe,Dynamic SQL(Compile time) ORM framework written in Rust, inspired by Mybatis and MybatisPlus.

rbatis 1.7k Jan 7, 2023
The rust client for CeresDB. CeresDB is a high-performance, distributed, schema-less, cloud native time-series database that can handle both time-series and analytics workloads.

The rust client for CeresDB. CeresDB is a high-performance, distributed, schema-less, cloud native time-series database that can handle both time-series and analytics workloads.

null 12 Nov 18, 2022
High performance and distributed KV store w/ REST API. 🦀

About Lucid KV High performance and distributed KV store w/ REST API. ?? Introduction Lucid is an high performance, secure and distributed key-value s

Lucid ᵏᵛ 306 Dec 28, 2022
🔥🌲 High-performance Merkle key/value store

merk High-performance Merkle key/value store Merk is a crypto key/value store - more specifically, it's a Merkle AVL tree built on top of RocksDB (Fac

Nomic 189 Dec 13, 2022
A high-performance, distributed, schema-less, cloud native time-series database

CeresDB is a high-performance, distributed, schema-less, cloud native time-series database that can handle both time-series and analytics workloads.

null 1.8k Dec 30, 2022