Skip to content

Added local queue scheduling and "next_task" optimization #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
af99c34
remove lifetime bound on State to simplify
nullchinchilla Mar 13, 2021
26bc361
remove
nullchinchilla Mar 13, 2021
faf2ff7
hack to make TLS work
nullchinchilla Mar 13, 2021
bb3d168
make run_pinned a future
nullchinchilla Mar 13, 2021
96e1d21
should be working now
nullchinchilla Mar 13, 2021
a6edf1b
remove concurrentqueue
nullchinchilla Mar 14, 2021
b99dd29
new benches
nullchinchilla Mar 14, 2021
99f067d
fix
nullchinchilla Mar 14, 2021
d27d960
actually fast
nullchinchilla Mar 14, 2021
16781cf
remove weak hack
nullchinchilla Mar 15, 2021
5d98fc4
fix stuff
nullchinchilla Mar 15, 2021
4edee8c
don't use local queues for nested execution
nullchinchilla Mar 15, 2021
0bfc883
tokio benches
nullchinchilla Mar 16, 2021
d378ddc
fixed
nullchinchilla Mar 16, 2021
1c3204c
attempt at next_task
nullchinchilla Mar 17, 2021
f0b426f
fix
nullchinchilla Mar 17, 2021
ddca550
fix call to num_cpus in tight loop
nullchinchilla Mar 17, 2021
dc8ef55
avoid starvation due to next_task by preventing two tasks in a row fr…
nullchinchilla Mar 17, 2021
96f78a4
remove debug statement
nullchinchilla Mar 17, 2021
ae542a1
revert
nullchinchilla Mar 17, 2021
cfeba8d
fix
nullchinchilla Mar 19, 2021
1a04003
crossbeam-deque
nullchinchilla Mar 22, 2021
6fd4b5c
fix nested
nullchinchilla Mar 23, 2021
88b8582
fix
nullchinchilla Mar 24, 2021
a449656
CORRECT yield detection
nullchinchilla Mar 26, 2021
f8a7515
further optimize performance
nullchinchilla Mar 27, 2021
66d1c50
reduce notify frequency even more
nullchinchilla Mar 27, 2021
3070a1d
test
nullchinchilla Mar 27, 2021
c0d33c6
sibling notification is now doubleplusgood
nullchinchilla Mar 27, 2021
e613c06
fix a bug...
nullchinchilla Mar 27, 2021
38f5454
artificially cripple sibling notification, yet again
nullchinchilla Mar 27, 2021
579ef5f
somewhat final version
nullchinchilla Mar 28, 2021
987eb42
small opt
nullchinchilla Mar 29, 2021
9319c4e
back to old sibling notification strategy to avoid certain starvation…
nullchinchilla Apr 4, 2021
b4f78c0
spsc
nullchinchilla Apr 18, 2021
297a001
spsc
nullchinchilla Apr 25, 2021
b1b70f9
1.4.1
nullchinchilla Apr 25, 2021
c86c95e
haha
nullchinchilla Apr 25, 2021
af94ae9
fix stuff getting lost
nullchinchilla Apr 30, 2021
acb5ba2
unfortunately we cannot use a next_task optimization, because the nex…
nullchinchilla May 14, 2021
0d6f0aa
revert
nullchinchilla May 15, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "async-executor"
version = "1.4.0"
version = "1.4.1"
authors = ["Stjepan Glavina <[email protected]>"]
edition = "2018"
description = "Async executor"
Expand All @@ -17,10 +17,25 @@ concurrent-queue = "1.2.2"
fastrand = "1.3.4"
futures-lite = "1.11.0"
once_cell = "1.4.1"
vec-arena = "1.0.0"
parking_lot = "0.11.1"
slab = "0.4.2"
cache-padded="1"
crossbeam-deque="0.8"

[dev-dependencies]
async-oneshot="0.5"
async-channel = "1.4.1"
async-io = "1.1.9"
easy-parallel = "3.1.0"
num_cpus = "1.13.0"
scopeguard="1.1"
criterion = "0.3"
num_cpus="1"

[profile.release]
incremental = true
debug = 2 # Set this to 1 or 2 to get more useful backtraces in debugger.
lto = 'thin'

[[bench]]
name = "my_benchmark"
harness = false
250 changes: 153 additions & 97 deletions benches/executor.rs
Original file line number Diff line number Diff line change
@@ -1,109 +1,165 @@
#![feature(test)]
// #![feature(test)]

extern crate test;
// extern crate test;

use std::future::Future;
// use std::future::Future;

use async_executor::Executor;
use futures_lite::{future, prelude::*};
// use async_executor::{Executor, Task};
// use futures_lite::{future, prelude::*};

const TASKS: usize = 300;
const STEPS: usize = 300;
const LIGHT_TASKS: usize = 25_000;
// const TASKS: usize = 300;
// const STEPS: usize = 300;
// const LIGHT_TASKS: usize = 25_000;

static EX: Executor<'_> = Executor::new();
// static EX: Executor<'_> = Executor::new();

fn run(f: impl FnOnce()) {
let (s, r) = async_channel::bounded::<()>(1);
easy_parallel::Parallel::new()
.each(0..num_cpus::get(), |_| future::block_on(EX.run(r.recv())))
.finish(move || {
let _s = s;
f()
});
}
// fn run(f: impl FnOnce()) {
// let (s, r) = async_channel::bounded::<()>(1);
// easy_parallel::Parallel::new()
// .each(0..num_cpus::get(), |_| future::block_on(EX.run(r.recv())))
// .finish(move || {
// let _s = s;
// f()
// });
// }

#[bench]
fn create(b: &mut test::Bencher) {
b.iter(move || {
let ex = Executor::new();
let task = ex.spawn(async {});
future::block_on(ex.run(task));
});
}
// #[bench]
// fn create(b: &mut test::Bencher) {
// b.iter(move || {
// let ex = Executor::new();
// let task = ex.spawn(async {});
// future::block_on(ex.run(task));
// });
// }

#[bench]
fn spawn_one(b: &mut test::Bencher) {
run(|| {
b.iter(move || {
future::block_on(async { EX.spawn(async {}).await });
});
});
}
// #[bench]
// fn spawn_one(b: &mut test::Bencher) {
// run(|| {
// b.iter(move || {
// future::block_on(async { EX.spawn(async {}).await });
// });
// });
// }

#[bench]
fn spawn_many(b: &mut test::Bencher) {
run(|| {
b.iter(move || {
future::block_on(async {
let mut tasks = Vec::new();
for _ in 0..LIGHT_TASKS {
tasks.push(EX.spawn(async {}));
}
for task in tasks {
task.await;
}
});
});
});
}
// #[bench]
// fn spawn_many(b: &mut test::Bencher) {
// run(|| {
// b.iter(move || {
// future::block_on(async {
// let mut tasks = Vec::new();
// for _ in 0..LIGHT_TASKS {
// tasks.push(EX.spawn(async {}));
// }
// for task in tasks {
// task.await;
// }
// });
// });
// });
// }

#[bench]
fn spawn_recursively(b: &mut test::Bencher) {
fn go(i: usize) -> impl Future<Output = ()> + Send + 'static {
async move {
if i != 0 {
EX.spawn(async move {
let fut = go(i - 1).boxed();
fut.await;
})
.await;
}
}
}
// #[bench]
// fn spawn_recursively(b: &mut test::Bencher) {
// fn go(i: usize) -> impl Future<Output = ()> + Send + 'static {
// async move {
// if i != 0 {
// EX.spawn(async move {
// let fut = go(i - 1).boxed();
// fut.await;
// })
// .await;
// }
// }
// }

run(|| {
b.iter(move || {
future::block_on(async {
let mut tasks = Vec::new();
for _ in 0..TASKS {
tasks.push(EX.spawn(go(STEPS)));
}
for task in tasks {
task.await;
}
});
});
});
}
// run(|| {
// b.iter(move || {
// future::block_on(async {
// let mut tasks = Vec::new();
// for _ in 0..TASKS {
// tasks.push(EX.spawn(go(STEPS)));
// }
// for task in tasks {
// task.await;
// }
// });
// });
// });
// }

#[bench]
fn yield_now(b: &mut test::Bencher) {
run(|| {
b.iter(move || {
future::block_on(async {
let mut tasks = Vec::new();
for _ in 0..TASKS {
tasks.push(EX.spawn(async move {
for _ in 0..STEPS {
future::yield_now().await;
}
}));
}
for task in tasks {
task.await;
}
});
});
});
}
// #[bench]
// fn yield_now(b: &mut test::Bencher) {
// run(|| {
// b.iter(move || {
// future::block_on(async {
// let mut tasks = Vec::new();
// for _ in 0..TASKS {
// tasks.push(EX.spawn(async move {
// for _ in 0..STEPS {
// future::yield_now().await;
// }
// }));
// }
// for task in tasks {
// task.await;
// }
// });
// });
// });
// }

// #[bench]
// fn context_switch_quiet(b: &mut test::Bencher) {
// let (send, mut recv) = async_channel::bounded::<usize>(1);
// let mut tasks: Vec<Task<Option<()>>> = vec![];
// for _ in 0..TASKS {
// let old_recv = recv.clone();
// let (new_send, new_recv) = async_channel::bounded(1);
// tasks.push(EX.spawn(async move {
// loop {
// new_send.send(old_recv.recv().await.ok()?).await.ok()?
// }
// }));
// recv = new_recv;
// }
// run(|| {
// b.iter(move || {
// future::block_on(async {
// send.send(1).await.unwrap();
// recv.recv().await.unwrap();
// });
// });
// });
// }

// #[bench]
// fn context_switch_busy(b: &mut test::Bencher) {
// let (send, mut recv) = async_channel::bounded::<usize>(1);
// let mut tasks: Vec<Task<Option<()>>> = vec![];
// for num in 0..TASKS {
// let old_recv = recv.clone();
// let (new_send, new_recv) = async_channel::bounded(1);
// tasks.push(EX.spawn(async move {
// loop {
// // eprintln!("forward {}", num);
// new_send.send(old_recv.recv().await.ok()?).await.ok()?;
// }
// }));
// recv = new_recv;
// }
// for _ in 0..TASKS {
// tasks.push(EX.spawn(async move {
// loop {
// future::yield_now().await;
// }
// }))
// }
// run(|| {
// b.iter(move || {
// future::block_on(async {
// send.send(1).await.unwrap();
// recv.recv().await.unwrap();
// });
// });
// });
// }
Loading