tokio 是 rust 生態(tài)中流行的異步運(yùn)行框架。在實(shí)際生產(chǎn)中我們?nèi)绻M?tokio 應(yīng)用程序與特定的 cpu core 綁定該怎么處理呢?這次我們來聊聊這個(gè)話題。
首先我們先寫一段簡(jiǎn)單的多任務(wù)程序。
use tokio::runtime;
pub fn main() {
let rt = runtime::new_multi_thread()
.enable_all()
.build()
.unwrap();
rt.block_on(async {
for i in 0..8 {
println!("num {}", i);
tokio::spawn(async move {
loop {
let mut sum: i32 = 0;
for i in 0..100000000 {
sum = sum.overflowing_add(i).0;
}
println!("sum {}", sum);
}
});
}
});
}
程序非常簡(jiǎn)單,首先構(gòu)造一個(gè)tokio runtime 環(huán)境,然后派生多個(gè) tokio 并發(fā),每個(gè)并發(fā)執(zhí)行一個(gè)無限循環(huán)做overflowing_add。overflowing_add函數(shù)返回一個(gè)加法的元組以及一個(gè)表示是否會(huì)發(fā)生算術(shù)溢出的布爾值。如果會(huì)發(fā)生溢出,那么將返回包裝好的值。然后取元祖的第一個(gè)元素打印。
這個(gè)程序運(yùn)行在 Ubuntu 20 OS,4 core cpu。通過nmon的監(jiān)控如下:
可以看到每個(gè) core 都有負(fù)載。
要想把負(fù)載綁定在某一 core 上,需要使用core_affinity_rs(https://github.com/Elzair/core_affinity_rs)。core_affinity_rs是一個(gè)用于管理CPU親和力的Rust crate。目前支持Linux、Mac OSX和Windows。官方宣稱支持多平臺(tái),本人只做了linux 操作系統(tǒng)的測(cè)試。
我們把代碼修改一下:
use tokio::runtime;
pub fn main() {
let core_ids = core_affinity::get_core_ids().unwrap();
println!("core num {}", core_ids.len());
let core_id = core_ids[1];
let rt = runtime::new_multi_thread()
.on_thread_start(move || {
core_affinity::set_for_current(core_id.clone());
})
.enable_all()
.build()
.unwrap();
rt.block_on(async {
for i in 0..8 {
println!("num {}", i);
tokio::spawn(async move {
loop {
let mut sum: i32 = 0;
for i in 0..100000000 {
sum = sum.overflowing_add(i).0;
}
println!("sum {}", sum);
}
});
}
});
}
在構(gòu)建多線程runtime時(shí),在on_thread_start 設(shè)置cpu親和。可以看到負(fù)載被綁定到了指定的core上。
上面的代碼只是把負(fù)載綁定到了一個(gè)core上,那么要綁定多個(gè)核怎么辦呢
我們看看下面的代碼
pub fn main() {
let core_ids = core_affinity::get_core_ids().unwrap();
println!("core num {}", core_ids.len());
let rt = runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
let mut idx = 2;
rt.block_on(async {
for i in 0..8 {
println!("num {}", i);
let core_id = core_ids[idx];
if idx.eq(&(core_ids.len() - 1)) {
idx = 2;
} else {
idx += 1;
}
tokio::spawn(async move {
let res = core_affinity::set_for_current(core_id);
println!("{}", res);
loop {
let mut sum: i32 = 0;
for i in 0..100000000 {
sum = sum.overflowing_add(i).0;
}
println!("sum {}", sum);
}
});
}
});
}
代碼需要把所有負(fù)載綁在 core3和core4上。原理是在派生任務(wù)中加入 core_affinity 設(shè)置.通過調(diào)整idx,將派生并發(fā)平均綁定在指定的core上。代碼運(yùn)行的監(jiān)控如下圖。
本期關(guān)于cpu親和的話題就聊到這兒,下期見
-
應(yīng)用程序
+關(guān)注
關(guān)注
37文章
3275瀏覽量
57732 -
Rust
+關(guān)注
關(guān)注
1文章
229瀏覽量
6614 -
Tokio
+關(guān)注
關(guān)注
0文章
12瀏覽量
65
原文標(biāo)題:文盤Rust -- tokio綁定cpu實(shí)踐
文章出處:【微信號(hào):Rust語言中文社區(qū),微信公眾號(hào):Rust語言中文社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論