我在OSX上有一个Rust应用程序启动大量线程,如下面的代码所示,但是,在查看我的OSX版本允许通过{{1}创建多少个最大线程数之后}命令,我可以看到它是sysctl kern.num_taskthreads
,它解释了为什么我不能超过2048个线程。
我如何才能超越这个硬限制?
kern.num_taskthreads: 2048
答案 0 :(得分:7)
在开始之前,我建议您阅读C10K problem。当你进入这个规模时,你需要记住更多的事情。
话虽如此,我建议看看mio ......
Rust的轻量级IO库,专注于在OS抽象上添加尽可能少的开销。
具体来说,mio提供了一个事件循环,它允许您处理大量连接而不会产生线程。不幸的是,我不知道当前支持mio的HTTP库。你可以创建一个并成为Rust社区的英雄!
答案 1 :(得分:1)
不确定这会有多大帮助,但我试图创建一个小的线程池来创建连接,然后通过一个通道将它们发送到事件循环进行读取。
我确定这段代码可能非常糟糕,但无论如何都是这样的例子。它使用Hyper库,就像你提到的那样。
extern crate hyper;
use std::io::Read;
use std::thread;
use std::thread::{JoinHandle};
use std::sync::{Arc, Mutex};
use std::sync::mpsc::channel;
use hyper::Client;
use hyper::client::Response;
use hyper::header::Connection;
const TARGET: i32 = 100;
const THREADS: i32 = 10;
struct ResponseWithString {
index: i32,
response: Response,
data: Vec<u8>,
complete: bool
}
fn main() {
// Create a client.
let url: &'static str = "http://www.gooogle.com/";
let mut threads = Vec::<JoinHandle<()>>::with_capacity((TARGET * 2) as usize);
let conn_count = Arc::new(Mutex::new(0));
let (tx, rx) = channel::<ResponseWithString>();
for _ in 0..THREADS {
// Move var references into thread context
let conn_count = conn_count.clone();
let tx = tx.clone();
let t = thread::spawn(move || {
loop {
let idx: i32;
{
// Lock, increment, and release
let mut count = conn_count.lock().unwrap();
*count += 1;
idx = *count;
}
if idx > TARGET {
break;
}
let mut client = Client::new();
// Creating an outgoing request.
println!("Creating connection {}...", idx);
let res = client.get(url) // Get URL...
.header(Connection::close()) // Set headers...
.send().unwrap(); // Fire!
println!("Pushing response {}...", idx);
tx.send(ResponseWithString {
index: idx,
response: res,
data: Vec::<u8>::with_capacity(1024),
complete: false
}).unwrap();
}
});
threads.push(t);
}
let mut responses = Vec::<ResponseWithString>::with_capacity(TARGET as usize);
let mut buf: [u8; 1024] = [0; 1024];
let mut completed_count = 0;
loop {
if completed_count >= TARGET {
break; // No more work!
}
match rx.try_recv() {
Ok(r) => {
println!("Incoming response! {}", r.index);
responses.push(r)
},
_ => { }
}
for r in &mut responses {
if r.complete {
continue;
}
// Read the Response.
let res = &mut r.response;
let data = &mut r.data;
let idx = &r.index;
match res.read(&mut buf) {
Ok(i) => {
if i == 0 {
println!("No more data! {}", idx);
r.complete = true;
completed_count += 1;
}
else {
println!("Got data! {} => {}", idx, i);
for x in 0..i {
data.push(buf[x]);
}
}
}
Err(e) => {
panic!("Oh no! {} {}", idx, e);
}
}
}
}
}