Skip to content

Commit

Permalink
🎉 public
Browse files Browse the repository at this point in the history
  • Loading branch information
Xudong-Huang committed Dec 18, 2017
0 parents commit 525d95c
Show file tree
Hide file tree
Showing 86 changed files with 13,883 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Compiled files
*.o
*.so
*.rlib
*.dll

# Executables
*.exe

# Generated by Cargo
/target/
Cargo.lock
17 changes: 17 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
sudo: false
language: rust
cache: cargo

os:
- linux
- osx

rust:
- nightly

evn:

- RUST_BACKTRACE=1

script:
- cargo test
51 changes: 51 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
[package]
name = "may"
version = "0.1.0"
authors = ["Xudong Huang <huangxu008@hotmail.com>"]
license = "LGPL-2.1"
repository = "https://github.com/Xudong-Huang/may.git"
homepage = "https://github.com/Xudong-Huang/may.git"
documentation = "https://docs.rs/may"
description = "Rust Coroutine Library"
readme = "README.md"
keywords = ["coroutine", "async", "multi thread"]
categories = ["concurrency"]
build = "build.rs"
exclude = [
".gitignore",
".travis.yml",
"appveyor.yml",
"benches/**/*",
]

[dependencies]
log = "0.3.6"
net2 = "0.2"
time = "0.1"
smallvec = "0.4"
generator = "0.6"
crossbeam = "0.3"
may_queue = { version = "0.1.0", path = "may_queue" }

[target.'cfg(unix)'.dependencies]
libc = "0.2"
nix = "0.9"

[target.'cfg(windows)'.dependencies]
miow = "0.2"
winapi = "0.2"
kernel32-sys = "0.2"

[dev-dependencies]
docopt = "0.8"
serde = "1.0"
serde_derive = "1.0"

[profile.release]
opt-level=3
lto = true

[build-dependencies]
rustc_version = "0.2"

[workspace]
504 changes: 504 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

84 changes: 84 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
[![Build Status](https://travis-ci.org/Xudong-Huang/may.svg?branch=master)](https://travis-ci.org/Xudong-Huang/may)
[![Build status](https://ci.appveyor.com/api/projects/status/7gv4kw3b0m0y1iy6/branch/master?svg=true)](https://ci.appveyor.com/project/Xudong-Huang/may/branch/master)
[![Current Crates.io Version](https://img.shields.io/crates/v/may.svg)](https://crates.io/crates/may)
[![Document](https://img.shields.io/badge/doc-may-green.svg)](https://docs.rs/may)
[![License](https://img.shields.io/github/license/Xudong-Huang/may.svg)](https://github.com/Xudong-Huang/may/blob/master/LICENSE)


# MAY

Rust Stackfull Coroutine Library

## Features

* Stackfull coroutine implementation based on [generator][1]
* Support schedule on configurable number of threads for multi-cores
* Support coroutine version local storage([CLS][cls])
* Support efficient network async IO
* Support efficient timer management
* Support standard sync primitives plus semphore, mpmc channel and more
* Support cancellation of coroutines
* Support graceful panic handling that will not affect other coroutines
* Support scoped coroutine creation
* Support general select for all the coroutine APIs
* All the coroutine APIs are compatible with std library semantics
* All the coroutine APIs can be safely called in thread context


## Usage
```rust
#[macro_use]
extern crate generator;
use generator::Gn;

fn main() {
let g = Gn::new_scoped(|mut s| {
let (mut a, mut b) = (0, 1);
while b < 200 {
std::mem::swap(&mut a, &mut b);
b = a + b;
s.yield_(b);
}
done!();
});

for i in g {
println!("{}", i);
}
}
```

## More examples

### CPU heavy load examples
* [quick sort][2]
* [prime number generator][3]

### IO heavy Bound examples
* [echo server][4]
* [echo client][5]
* [coroutine based hyper][6]


## Performance
* As far as I can tell the io performance can compare with [mio][7], but I didn't test them throughly


## Notices
* both stable and nightly rust compiler are supported
* This crate supports below platforms, for more platform support, please ref [generator][1]

- x86_64 Linux
- x86_64 MacOs
- x86_64 Windows

[1]:https://github.com/Xudong-Huang/generator-rs
[2]:https://github.com/Xudong-Huang/generator-rs
[3]:https://github.com/Xudong-Huang/generator-rs
[4]:https://github.com/Xudong-Huang/generator-rs
[5]:https://github.com/Xudong-Huang/generator-rs
[6]:https://github.com/Xudong-Huang/generator-rs
[7]:https://github.com/Xudong-Huang/generator-rs
[8]:https://github.com/Xudong-Huang/generator-rs
[9]:https://github.com/Xudong-Huang/generator-rs
[cls]:https://blog.zhpass.com/2017/12/18/CLS/
19 changes: 19 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
environment:
RUST_BACKTRACE: 1
matrix:
- TARGET: x86_64-pc-windows-gnu
MSYS2_BITS: 64
- TARGET: x86_64-pc-windows-msvc

install:
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
- rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
- if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin
- rustc -V
- cargo -V

build: false

test_script:
- cargo test
172 changes: 172 additions & 0 deletions benches/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#![cfg(nightly)]
#![feature(test)]
extern crate may;
extern crate test;

// use std::panic;
use may::coroutine;
use coroutine::*;
use test::Bencher;

#[bench]
fn yield_bench(b: &mut Bencher) {
// don't print any panic info
// when cancel the generator
// panic::set_hook(Box::new(|_| {}));
b.iter(|| {
let h = spawn(|| for _i in 0..10000 {
yield_now();
});

h.join().unwrap();
});
}


#[bench]
fn spawn_bench(b: &mut Bencher) {
may::config().set_workers(4);
b.iter(|| {
let total_work = 1000;
let threads = 2;
let mut vec = Vec::with_capacity(threads);
for _t in 0..threads {
let j = std::thread::spawn(move || {
scope(|scope| {
for _i in 0..total_work / threads {
scope.spawn(|| {
// yield_now();
});
}
});
});
vec.push(j);
}
for j in vec {
j.join().unwrap();
}
});
}

#[bench]
fn spawn_bench_1(b: &mut Bencher) {
may::config().set_workers(4);
b.iter(|| {
let total_work = 1000;
let threads = 2;
let mut vec = Vec::with_capacity(threads);
for _t in 0..threads {
let work = total_work / threads;
let j = std::thread::spawn(move || {
let v = (0..work)
.map(|_| coroutine::spawn(|| {}))
.collect::<Vec<_>>();
for h in v {
h.join().unwrap();
}
});
vec.push(j);
}
for j in vec {
j.join().unwrap();
}
});
}

#[bench]
fn smoke_bench(b: &mut Bencher) {
may::config().set_workers(4).set_pool_capacity(10000);
b.iter(|| {
let threads = 5;
let mut vec = Vec::with_capacity(threads);
for _t in 0..threads {
let j = std::thread::spawn(|| {
scope(|scope| for _i in 0..200 {
scope.spawn(|| for _j in 0..1000 {
yield_now();
});
});
});
vec.push(j);
}
for j in vec {
j.join().unwrap();
}
});
}

#[bench]
fn smoke_bench_1(b: &mut Bencher) {
may::config().set_workers(4).set_pool_capacity(10000);
b.iter(|| {
let threads = 5;
let mut vec = Vec::with_capacity(threads);
for _t in 0..threads {
let j = std::thread::spawn(|| {
scope(|scope| for _i in 0..2000 {
scope.spawn(|| for _j in 0..4 {
yield_now();
});
});
});
vec.push(j);
}
for j in vec {
j.join().unwrap();
}
});
}

#[bench]
fn smoke_bench_2(b: &mut Bencher) {
may::config().set_workers(4);
b.iter(|| {
scope(|s| {
// create a main coroutine, let it spawn 10 sub coroutine
for _ in 0..100 {
s.spawn(|| {
scope(|ss| {
for _ in 0..100 {
ss.spawn(|| {
// each task yield 4 times
for _ in 0..4 {
yield_now();
}
});
}
});
});
}
});
});
}

#[bench]
fn smoke_bench_3(b: &mut Bencher) {
may::config().set_workers(4);
b.iter(|| {
let mut vec = Vec::with_capacity(100);
// create a main coroutine, let it spawn 10 sub coroutine
for _ in 0..100 {
let j = spawn(|| {
let mut _vec = Vec::with_capacity(100);
for _ in 0..100 {
let _j = spawn(|| {
// each task yield 10 times
for _ in 0..4 {
yield_now();
}
});
_vec.push(_j);
}
for _j in _vec {
_j.join().ok();
}
});
vec.push(j);
}
for j in vec {
j.join().ok();
}
});
}
10 changes: 10 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
extern crate rustc_version;

use rustc_version::{version_meta, Channel};

fn main() {
// Set cfg flags depending on release channel
if let Channel::Nightly = version_meta().unwrap().channel {
println!("cargo:rustc-cfg=nightly");
}
}
Loading

0 comments on commit 525d95c

Please sign in to comment.