什么是未来的RS封装阻塞I / O的最佳方法?什么是未来的RS封装阻塞I / O的最佳方法?(Wha

2019-05-12 08:18发布

我读了TOKIO的文件 ,我不知道什么是在未来的封装成本同步I / O的最佳途径。

随着反应器框架,我们得到了一个绿色的线程模型的优点是:几个操作系统的线程通过执行处理大量并发任务。

TOKIO的未来模式是需求驱动,这意味着今后本身将查询其内部状态提供有关其完成信息; 允许背压和取消功能。 据我了解,未来的轮询阶段必须是非阻塞运行良好。

在I / O口需要封装可以被看作是一个长期的原子和昂贵的操作。 理想情况下,一个独立的任务将执行I / O和相关的未来将轮询完成状态的I / O线程。

我看到这两个唯一的选项是:

  • 包括在阻塞I / O poll未来的功能。
  • 产卵的OS线程以执行I / O,并使用未来机制轮询其状态下,如示出的文档中

据我所知,没有解决方案是最佳的,并且没有得到充分利用的绿色线程模型(第一次没有在文档劝和第二不通过由电抗器框架提供的执行)。 有另一种解决方案?

Answer 1:

理想情况下,一个独立的任务将执行I / O和相关的未来将轮询完成状态的I / O线程。

是的,这就是东京建议和像什么箱子期货cpupool和TOKIO,线程池的创建。 请注意,这并不局限于I / O,而且是有效的任何长期运行的同步任务!

在这种情况下,您计划关闭在池中运行。 池本身进行工作检查,看看是否阻塞闭合尚未完成,并满足Future特质。

extern crate futures;
extern crate futures_cpupool;

use futures::{future, Future};
use futures_cpupool::CpuPool;
use std::thread;
use std::time::Duration;

fn main() {
    let pool = CpuPool::new(8);

    let a = pool.spawn_fn(|| {
        thread::sleep(Duration::from_secs(3));
        future::ok::<_, ()>(3)
    });
    let b = pool.spawn_fn(|| {
        thread::sleep(Duration::from_secs(1));
        future::ok::<_, ()>(1)
    });

    let c = a.join(b).map(|(a, b)| a + b);

    let result = c.wait();
    println!("{:?}", result);
}

请注意,这是睡觉的有效方式,它只是对一些阻塞操作的占位符。 如果你确实需要睡觉,使用类似期货定时器或TOKIO定时器 。

你可以看到,总的时间仅为3秒:

$ time ./target/debug/example
Ok(4)

real    0m3.021s
user    0m0.007s
sys     0m0.010s

同样,你可以使用TOKIO,线程池的相同的结果:

extern crate tokio; // 0.1.7
extern crate tokio_threadpool; // 0.1.2

use std::{thread, time::Duration};
use tokio::{prelude::*, runtime::Runtime};

fn delay_for(seconds: u64) -> impl Future<Item = u64, Error = tokio_threadpool::BlockingError> {
    future::poll_fn(move || {
        tokio_threadpool::blocking(|| {
            thread::sleep(Duration::from_secs(seconds));
            seconds
        })
    })
}

fn main() {
    let a = delay_for(3);
    let b = delay_for(1);
    let sum = a.join(b).map(|(a, b)| a + b);

    let mut runtime = Runtime::new().expect("Unable to start the runtime");
    let result = runtime.block_on(sum);
    println!("{:?}", result);
}

无论解决方案是最佳的,并且没有得到充分利用的绿色线程模型

这是正确的 - 因为你没有的东西,是异步的! 您正在尝试两种不同的方法结合起来,必须有一个丑陋的地方一点对他们之间的转换。

第二不穿过由反应器框架提供的执行程序

我不知道你的意思在这里。 这里只有一个在上面的例子中执行; 通过隐含创建的wait 。 线程池有检查,看看如果一个线程是做了一些内部逻辑,但是当用户执行程序,它应该只被触发poll这样。



文章来源: What is the best approach to encapsulate blocking I/O in future-rs?