Skip to content

Commit 6df02c8

Browse files
perf(driver): set setup_coop_taskrun for io-uring (#401)
* perf(driver): set setup_coop_taskrun for io-uring this can optimize performance for most cases * feat(driver): allow user to choose enable coop_taskrun and taskrun_flag or not
1 parent af71743 commit 6df02c8

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

compio-driver/src/iour/mod.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ impl Driver {
100100
if let Some(sqpoll_idle) = builder.sqpoll_idle {
101101
io_uring_builder.setup_sqpoll(sqpoll_idle.as_millis() as _);
102102
}
103+
if builder.coop_taskrun {
104+
io_uring_builder.setup_coop_taskrun();
105+
}
106+
if builder.taskrun_flag {
107+
io_uring_builder.setup_taskrun_flag();
108+
}
109+
103110
let mut inner = io_uring_builder.build(builder.capacity)?;
104111
#[allow(clippy::useless_conversion)]
105112
unsafe {
@@ -127,14 +134,23 @@ impl Driver {
127134
// Auto means that it choose to wait or not automatically.
128135
fn submit_auto(&mut self, timeout: Option<Duration>) -> io::Result<()> {
129136
instrument!(compio_log::Level::TRACE, "submit_auto", ?timeout);
137+
138+
// when taskrun is true, there are completed cqes wait to handle, no need to
139+
// block the submit
140+
let want_sqe = if self.inner.submission().taskrun() {
141+
0
142+
} else {
143+
1
144+
};
145+
130146
let res = {
131147
// Last part of submission queue, wait till timeout.
132148
if let Some(duration) = timeout {
133149
let timespec = timespec(duration);
134150
let args = SubmitArgs::new().timespec(&timespec);
135-
self.inner.submitter().submit_with_args(1, &args)
151+
self.inner.submitter().submit_with_args(want_sqe, &args)
136152
} else {
137-
self.inner.submit_and_wait(1)
153+
self.inner.submit_and_wait(want_sqe)
138154
}
139155
};
140156
trace!("submit result: {res:?}");

compio-driver/src/lib.rs

+31
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,8 @@ pub struct ProactorBuilder {
438438
capacity: u32,
439439
pool_builder: ThreadPoolBuilder,
440440
sqpoll_idle: Option<Duration>,
441+
coop_taskrun: bool,
442+
taskrun_flag: bool,
441443
}
442444

443445
impl Default for ProactorBuilder {
@@ -453,6 +455,8 @@ impl ProactorBuilder {
453455
capacity: 1024,
454456
pool_builder: ThreadPoolBuilder::new(),
455457
sqpoll_idle: None,
458+
coop_taskrun: false,
459+
taskrun_flag: false,
456460
}
457461
}
458462

@@ -516,6 +520,33 @@ impl ProactorBuilder {
516520
self
517521
}
518522

523+
/// `coop_taskrun` feature has been available since Linux Kernel 5.19. This
524+
/// will optimize performance for most cases, especially compio is a single
525+
/// thread runtime.
526+
///
527+
/// However, it can't run with sqpoll feature.
528+
///
529+
/// # Notes
530+
///
531+
/// - Only effective when the `io-uring` feature is enabled
532+
pub fn coop_taskrun(&mut self, enable: bool) -> &mut Self {
533+
self.coop_taskrun = enable;
534+
self
535+
}
536+
537+
/// `taskrun_flag` feature has been available since Linux Kernel 5.19. This
538+
/// allows io-uring driver can know if any cqes are available when try to
539+
/// push sqe to sq. This should be enabled with
540+
/// [`coop_taskrun`](Self::coop_taskrun)
541+
///
542+
/// # Notes
543+
///
544+
/// - Only effective when the `io-uring` feature is enabled
545+
pub fn taskrun_flag(&mut self, enable: bool) -> &mut Self {
546+
self.taskrun_flag = enable;
547+
self
548+
}
549+
519550
/// Build the [`Proactor`].
520551
pub fn build(&self) -> io::Result<Proactor> {
521552
Proactor::with_builder(self)

0 commit comments

Comments
 (0)