Giter VIP home page Giter VIP logo

omango's Introduction

Pngtree-omango-in-flat-style-omango-3626110


Rust License: MIT Release Cargo Rust 1.49+


Omango

This is a concurrency collection.

  • Support lock-free SPSC and MPMC queue (bounded and unbounded). The queues are simple, lightweight, fast and safe in multithreading environment. It is faster than std::mpsc::sync_channel and other open source's bounded queue ( ringbuf, rtrb, flume, crossbeam-channel ).

  • Support Golang WaitGroup waits for a collection of threads to finish.

  • Support Single Flight multiplexing threads that have the same work and only one represent thread will run and returns response for all waiting threads.

  • Support Single Source provide mechanism to synthesize response from multiple sources.

Table of Contents

Introduction

Both SPSC and MPMC queue are implemented based on pseudocode of Dmitry Vyukov. The implementation way is exactly the same. But there are still some differences between them about wait-retry and blocking.

MPMC is high contention multithreading environment. If the retry is continuous and immediate, the CPU cache coherence will be increased rapidly and decrease performance. Therefore, we must wait then retry. However, this thing is unsuitable in SPSC is lower contention multithreading environment (Just 2 threads). In SPSC, the immediate retry still guarantees performance.

Both SPSC and MPMC queue can be used as channels.

Compared with version 0.1.*

  • Performance is better.

  • Supported unbounded queues (SPSC + MPMC).

  • Can use recv to get remaining items when the queue was closed.

Usage

Add this to your Cargo.toml:

[dependencies]
omango = "0.2.5"

Compatibility

The minimum supported Rust version is 1.57.

Benchmarks

Tests were performed on an Intel Core I7 with 4 cores running Windows 11 and M1 with 8 cores running macOS BigSur 11.3.

Omango benchmarks SPSC

Omango benchmarks MPSC

Omango benchmarks MPMC

Omango benchmarks Unbounded

License

The crate is licensed under the terms of the MIT license. See LICENSE for more information.

Reference

omango's People

Contributors

tqtrungse avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

omango's Issues

Assume RISC-V uses 64-byte lines

If I'm not mistaken,

target_arch = "riscv64",

seems to assume RISC-V uses 32-byte lines. RISC-V didn't originally define the line size, but recent extension Zic64b defines the line as 64-bytes and this is empirically observed to be the common choice for RV64 implementations (same for Aarch64 I'd assume, but haven't checked).

An alignment of 32-bytes will hurt performance on a 64-byte line implementation, where the reverse will [just] waste memory.

Benchmarks too short?

I did some timing measurements on your benchmarks (for non-blocking SPSC) and I found that only a small part of them measure the multi-threaded behavior of the queue.

Here are some timings that I measured:

The benchmarks include the time for the creation and initialization of the queue, but that's not a big deal, since that's less than 2 usec.

More importantly, it also measures the creation of the thread, which means that the main thread starts reading from the queue only after about 30 usec.

But the second thread is not fully running yet, it takes another 25 usec or so until it starts writing to the queue.

The actual parallel writing and reading then only takes 25 to 30 usec.

Closing the thread then also takes about 25 to 30 usec.

All in all, the parallel processing (which I guess is what we want to benchmark, right?) is only less than a third of the total time.

I think it would be better to increase the number of elements sent over the queue (at least by 10x, but maybe 100x), in order for most of the measured time to be actually spent during parallel processing.

What do you think?

Questions around explicit channel closing

Hi,

While trying omango out as a crossbeam_channel replacement, I was surprised that the Sender<MyType> going out of scope doesn't close() the channel, and that explicitly closing the sender makes the corresponding rx.recv() immediately fail even if there are messages left in the channel. I could get them with try_recv(), but then would have to deal with the non-blocking API.

Am I missing something, or is omango not intended for the "send finite list of items from one thread to another" usecase ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.