tokio多任务绑定cpu(绑核)

news/2024/9/22 22:40:36/

tokio 是 rust 生态中流行的异步运行时框架。在实际生产中我们如果希望 tokio 应用程序与特定的 cpu core 绑定该怎么处理呢?

首先我们先写一段简单的多任务程序。

rust">use tokio;
use tokio::runtime;
use core_affinity;fn tokio_sample() {let rt = runtime::Builder::new_multi_thread().enable_all().build().unwrap();rt.block_on(async {for i in 0..4 {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);}});}});
}fn main() {tokio_sample();   
}

程序非常简单,首先构造一个 tokio runtime 环境,然后派生多个 tokio 并发,每个并发执行一个无限循环做 overflowing_add。overflowing_add 函数返回一个加法的元组以及一个表示是否会发生算术溢出的布尔值。如果会发生溢出,那么将返回包装好的值。然后取元祖的第一个元素打印。

这个程序运行在 Centos8,4 core cpu。通过 pidstat -t 1 -p $(pidof cpu_affinity_tokio) 的监控如下:

在这里插入图片描述

可以看到4个 core 负载几乎都是 100%。

要想把负载绑定在某一 core 上,需要使用 core_affinity_rs。core_affinity_rs 是一个用于管理 CPU 亲和力的 Rust crate。目前支持 Linux、Mac OSX 和 Windows。官方宣称支持多平台。

我们把代码修改一下:

rust">fn tokio_affinity_cpu1() {let core_ids = core_affinity::get_core_ids().unwrap();println!("core num {}", core_ids.len());let core_id = core_ids[1];let rt = runtime::Builder::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..4 {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);}});}});
}fn main() {  tokio_affinity_cpu1();
}

在构建多线程 runtime 时,在 on_thread_start 设置 cpu 亲和 cpu1。可以看到负载被绑定到了指定的 core 上,4 个线程各占 1/4 cpu。

在这里插入图片描述

上面的代码只是把负载绑定到了一个 core 上,那么要绑定多个核怎么办呢?
我们看看下面的代码

rust">fn tokio_affinity_cpu1_cpu2() {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 = 1;rt.block_on(async {for i in 0..4 {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);}});}});
}fn main() {tokio_affinity_cpu1_cpu2();
}

代码需要把所有负载绑在 core1 和 core2 上。原理是在派生任务中加入 core_affinity 设置。通过调整 idx,将派生并发平均绑定在指定的 core 上。代码运行的监控如下图。

在这里插入图片描述

参考:
文盘 Rust – tokio 绑定 cpu 实践
Rust入门秘籍-tokio简介
Rust语言圣经(Rust Course)-tokio
https://tokio.rs/tokio/tutorial


http://www.ppmy.cn/news/1442186.html

相关文章

LIUNX:系统编程动态库加载(1)

目录 操作系统角度理解 如何加载 怎么管理库 编址 操作系统角度理解 如何加载 首先main想要运行,首先要为main创建task_struct和mm_struct,然后将main的代码和数据加载到内存,将main的代码通过页表映射到mm_struct的正文代码段&#xff0…

three.js vue3封装贴图循环偏移案例

以上是代码实现效果。本篇文章主要讲述vue3对代码的封装&#xff0c;以及如何让图片循环播放。 封装主要分三步&#xff1a; 1、封装实例化模块&#xff1b;2、封装渲染&#xff1b;3、偏移量操作。 具体的代码如下&#xff1a; <script setup> import * as THREE fr…

Unity打开Android文件管理器并加载文件

1、在AssetStore商店中加入免费插件 2、调用代码 3、使用UnityWebRequest加载路径数据

10 SQL进阶 -- 综合练习题 -- 10道经典SQL题目,配套数据与解答

1. 创建表结构和导入数据 1.1 新建数据库 1.2 执行建表语句 点击下方链接直接下载创建数据表脚本:http://tianchi-media.oss-cn-beijing.aliyuncs.com/dragonball/SQL/create_table.sql 执行建表语句执行成功查看创建的表1.3 导入数据 点击下方链接直接下载插入数据脚本:htt…

pymilvus执行多向量搜索

pymilvus执行多向量搜索 从 Milvus 2.4 开始&#xff0c;引入了多向量支持和混合搜索框架&#xff0c;单个collection可以支持10个向量字段。不同的向量字段可以表示不同的方面、不同的embedding模型甚至表征同一实体的不同数据模态。该功能在综合搜索场景中特别有用&#xff…

ElasticSearch自动补全

一、拼音分词器&#xff1a; 当用户在搜索框输入字符时&#xff0c;我们应该提示出与该字符有关的搜索项&#xff0c;如图&#xff1a; 这种根据用户输入的字母&#xff0c;提示完整词条的功能&#xff0c;就是自动补全了。 GET /_analyze {"text":"我爱螺蛳粉…

Java try catch 应该在 for 循环里面还是外面?(面试)

时间上&#xff0c; 其实算是无差别。内存上&#xff0c; 如果没出异常&#xff0c;其实也是无差别。 但是如果出现了异常&#xff0c; 那就要注意了。 一、try catch 在 for 循环外面 public static void tryOutside() { try { for (int count 1; count < 5; count) …

kotlin 编写一个简单的天气预报app (七)使用material design

一、优化思路 对之前的天气预报的app进行了优化&#xff0c;原先的天气预报程序逻辑是这样的。 使用text和button组合了一个输入城市&#xff0c;并请求openweathermap对应数据&#xff0c;并显示的功能。 但是搜索城市的时候&#xff0c;可能会有错误&#xff0c;比如大小写…