Rust中的高吞吐量流处理
本篇文章主要介绍了Rust中流处理的概念、方法和优化。作者不仅介绍了流处理的基本概念以及Rust中常用的流处理库,还使用这些库实现了一个流处理程序。
最后,作者介绍了如何通过测量空闲和阻塞时间来优化流处理程序的性能,并将这些内容同步至Twitter和blog。

此外,作者还提供了一些其它方面的优化建议,例如:
- 在实际系统中,应考虑将线程固定至CPU内核上或使用一种版本的绿色线程减少上下文切换。
- 在处理流时,通常需要为结果分配内存。内存分配是昂贵的,所以,在以后的文章中,作者将会介绍一些优化内存分配的好方法。
首先,分别介绍下在同步和异步Rust中的流特质。
一、同步和异步Rust中的流特质
在同步Rust中,流核心抽象是Iterator。它提供了在序列中产生项的方法并在它们之间进行阻塞,然后,通过将迭代器传递给其它迭代器的构造函数完成组合。这使我们可以毫不费力地将事物连接在一起。
在异步Rust中,流核心抽象是Stream。它的行为与Iterator非常相似;但是,它并不是在每个项之间产生的阻塞,而是允许其它任务在阻塞等待时运行。
在异步Rust与同步Rust中,Read和Write分别对应AsyncRead和AsyncWrite。这些特质表明:未解析的字节通常直接来自10层(例如,来自套接字或文件)。

Rust流吸收了其它语言所具备的最佳功能;例如,它们能通过利用Rust特质系统回避Node.js的Duplex流中出现的遗留问题,也能同时实施背压和惰性迭代,大大提升了效率。最重要的是,Rust流允许使用相同类型的异步迭代。
未来,关于Rust流还有很多值得关注之处,尽管仍有一些问题亟待解决。
二、总体概括:什么是流处理?
现在,也许你已经了解到了同步和异步Rust中的流特质,下面再来介绍下什么是“流处理”。
“流处理”是一种重要的大数据处理手段,其主要特点是处理的数据是源源不断且实时到来的。
在不同规模的科技公司中,流处理通常被用于分析和处理具体事件,且常被应用于分布式系统。
有些领域确实会大量使用“流处理”手段,包括:视频处理和高频交易。我们也能够借此寻找到新型区块链之中的架构灵感。因为,区块链需要处理交易和元数据流等。
如今,你可以租用具有100多个CPU的内核、100GB内存、多个GPU和100Gbps带宽的AWS实例,还无需拥有一个节点的分布式系统。
现在,让我们了解下流处理在Rust编程中的应用:
三、举个例子:计算10亿个数字的哈希程序
现在,让我们写一个用来计算10亿个数字的SHA512和BLAKE3哈希程序吧!你可以想象:数字代表交易、分析事件或价格信号。散列法可用来表示对这些输入的任意转换。
如下是单线程解决方案程序:

当我在带有专用CPU和16核的Digital Ocean上用发布模式运行此程序时,只需6分钟多一点。

1.通道
现在,让我们用“流处理”来重写这个程序。与在单个循环中执行散列不同,我们将设置一个线程管道并行执行散列,然后收集结果。
在两个线程之间发送数据的本地流被称为通道。我们的新程序将生成四个线程。生成器线程将生成数字并同时将它们发送至两个不同的哈希线程。散列线程将读取这些数字,分别对它们进行散列,然后将它们的输出发送给结果线程,下图是它的架构:

我们也将使用标准库中的mpsc通道发送和接收数据。mpsc可用来表示“多生产者-单消费者”,代表你可以从多个线程向通道发送数据,但是,只有一个管道能够输出数据。虽然我们不会使用这个多制作人功能,但是了解这一点很重要。
它仍是一个相当简单的程序:

输出结果如下:
![]()
哦!带通道的新版本花费了两倍时间,这是怎么了?
2.环形缓冲器
你可以用火焰图进行测试,但还是省省时间吧!
无论多小,所有通道库的构建都会产生额外的费用,并行化所带来的好处必须大于此种开销,才能保证系统正常运作。这种情况下的瓶颈是通道send()和recv()。由于Rust中的标准库mpsc通道相对缓慢,但仍有其它替代方案,比如,crossbeam-channel。
为此,我们分析了4个不同的通道库,结果如下:

显然,ringbuf和rtrb速度最快。因为它们的环形缓冲区无锁,扮演着“单个生产者-单个消费者”的角色。单个生产者意味着只有一个管道将数据放入队列,另一个管道将负责数据输出,这比“多生产者队列”开销小。
此外,这些程序库也是非阻塞式的。当队列已满时,如果尝试推送,它将提示“error”而不是“block”,“空队列”亦是如此。
为使用这些环形缓冲区库,我添加了自旋锁,以便在通道阻塞时继续重试。事实证明,这也是高频交易架构中所使用的方法。
我还发现,在等待时增加非常短的“休眠”时间整体性能就能提高。这可能是由于当核心使用率达到100%或高于某些温度时,启动CPU就会发生节流的现象。
如下是新的pop()和push(value)帮助器:

我们将用新方法展示:

速度确实比以前快了,但也快不了多少,现在,就让我们把并行化提升至另一个层次。
3.更多的并行化
目前,我们为哈希创建了两个线程,一个用于SHA512,另一个用于BLAKE3。两者中较慢的那个将成为我们技术发展的瓶颈。为证明这一点,我重新运行了原始的单线程示例,仅使用SHA512哈希,结果如下:

这与并行哈希示例中的性能非常接近,意味着,总体上花在哈希上的大部分时间都是由SHA512产生。
那么,如果我们同时创建更多的线程并将多个数字进行散列排列呢?让我们试一试。我们将创建2个SHA512哈希线程和2个BLAKE3哈希线程来启动。
4.可视化
每个线程都拥有自己的输入和输出队列。我们将用循环顺序将生成的数字循环发送至每个线程并用相同的顺序读取结果。

这确保了流的顺序能够在结果线程中维持不变;如果排序不重要或消息处理时间多变,那么,其它的调度机制可能会更好。
如下是循环调度代码:

新的代码更复杂,部分如下:

一起来看看,现在表现如何?输出结果如下:
![]()
确实好多了!
5.测量“闲置”和“阻塞”时间
每个哈希函数应该有多少个线程?在更复杂的系统中,这很难确定,甚至可能是动态的。
实际上,有一种技术对“流处理”很有帮助,即,在某个时间窗口内测量空闲和阻塞时间。
- 空闲时间
等待空队列接收消息所花的时间
- 全程时间
等待满队列发送输出所花费的时间
空闲时间是pop()期间旋转的时间,阻塞时间是push()期间旋转的时间。我修改了这两个函数,用来跟踪花费时间。这段代码使用了开销很小的单元:

我还创建了一个新的线程统计这些时间,输出结果如下:

我们可以看到,sha512线程既没有“空闲”也没有“阻塞”,而是100%处于活跃状态;此外,我们还能通过增加sha512线程数量为系统提速。
注:当用测量系统的行为改变其性能时,可能会出现像“海森伯测不准原理”这样的问题。如果遇到此种情况,请查看“粗时间库”;通常,定时测量取近似值就足够了。
我们在Digital Ocean实例中,经过试验和错误数据总结出:最佳数量是8个SHA512线程和4个BLAKE3线程。
![]()
结果:小于初始时间的1/6。
四、下一步:为不同的流处理结果分配内存
在这篇文章中,我们用具体实例介绍了Rust中流处理的概念、方法和优化,但是还有很多细节没有讨论。在实际系统中,我们应该考虑将“线程”固定到CPU内核上,用来减少上下文切换。
此外,在流处理时,你通常需要为不同的结果分配内存。这是昂贵的,所以,在今后的文章中,我们还将讨论这方面的一些策略。
多看看优秀的前沿工具
太空电梯、MOSS、ChatGPT等,都预兆着2023年注定不会是平凡的一年。任何新的技术都值得推敲,我们应要有这种敏感性。
这几年隐约碰过低代码,目前比较热门,很多大厂都相继加入。
低代码平台概念:通过自动代码生成和可视化编程,只需要少量代码,即可快速搭建各种应用。
到底啥是低代码,在我看来就是拖拉拽,呼呼呼,一通操作,搞出一套能跑的系统,前端,后端,数据库,一把完成。当然这可能是最终目标。
链接:www.jnpfsoft.com/?csdn,如果你感兴趣,也体验一下。
JNPF的优势就在于它能生成前后台代码,提供了极大的灵活性,能够创建更复杂、定制化的应用。它的架构设计也让开发者无需担心底层技术细节,能够专注于应用逻辑和用户体验的开发。
相关文章:
Rust中的高吞吐量流处理
本篇文章主要介绍了Rust中流处理的概念、方法和优化。作者不仅介绍了流处理的基本概念以及Rust中常用的流处理库,还使用这些库实现了一个流处理程序。 最后,作者介绍了如何通过测量空闲和阻塞时间来优化流处理程序的性能,并将这些内容同步至…...
探索编程世界的宝藏:程序员必掌握的20大算法
文章目录 1 引言2 冒泡排序算法:编程世界的排序魔法 🧙♀️🔢3 选择排序算法:排序世界的精确挑选器 🎯🔢4 插入排序算法:排序世界的巧妙插珠者 ✨🔢5 快速排序算法:排序…...
Android NFC通信示例
前言 近距离无线通信 (NFC) 是一组近距离无线技术,通常只有在距离不超过 4 厘米时才能启动连接。借助 NFC,您可以在 NFC 标签与 Android 设备之间或者两台 Android 设备之间共享小型负载。 支持 NFC 的 Android 设备同时支持以下三种主要操作模式&…...
2023年08月IDE流行度最新排名
点击查看最新IDE流行度最新排名(每月更新) 2023年08月IDE流行度最新排名 顶级IDE排名是通过分析在谷歌上搜索IDE下载页面的频率而创建的 一个IDE被搜索的次数越多,这个IDE就被认为越受欢迎。原始数据来自谷歌Trends 如果您相信集体智慧&am…...
使用Beego和MySQL实现帖子和评论的应用,并进行接口测试(附源码和代码深度剖析)
文章目录 小项目介绍源码分析main.gorouter.gomodels/user.gomodels/Post.gomodels/comment.gocontrollers/post.gocontrollers/comment.go 接口测试测试增加帖子测试查看帖子测试增加评论测试查看评论 小项目介绍 经过对需求的分析,我增加了一些额外的东西&#x…...
物联网潜在的巨大价值在于大数据分析
物联网潜在的巨大价值在于大数据分析 从数据里去挖掘市场或者用户的精准需求。 往小的说,后台可以统计用户家里各各插座一年甚至更久的用电情况,这些数据也可以通过app或者小程序展现给用户。 用户可以很直观看到自己一年的用电情况,哪个家…...
SSL原理详解
SSL协议结构: SSL协议分为两层,下层为SSL记录协议,上层为SSL握手协议、SSL密码变化协议和SSL警告协议。 1.下层为SSL记录协议,主要作用是为高层协议提供基本的安全服务 建立在可靠的传输之上,负责对上层的数据进行分块…...
linux下的etc目录代表什么意思
在Linux系统中,/etc目录是一个非常重要的目录,它包含了系统的配置文件和相关的配置信息。下面是一些/etc目录中常见的文件和目录: 1. /etc/passwd:此文件包含了所有用户账户的信息,包括用户名、用户ID、用户所属的组I…...
iOS 两种方式设置状态栏
1、ios9.0以前设置状态栏字体颜色 ///白色 [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent]; ///黑色 [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleDefault]; 会看到如下提示: setStatusBarSty…...
html5:webSocket 基础使用
一、理解 HTML5 WebSocket HTML5 WebSocket是一种新型的网络协议,它能够在客户端和服务器之间建立实时的双向通信通道,使得浏览器和服务器之间的数据传输更加高效、快速和可靠。相比传统的HTTP协议,WebSocket协议使用更少的网络开销…...
html学习10-----总结(完)
<!DOCTYPE html> <html><head><meta charset"utf-8"/><title>html总结</title></head><body><h1>HTML总结</h1><br/><h2>文本格式化</h2><hr/><p><b>粗体文本<…...
Spring使用P命名空间实现注入数值信息-----Spring框架
<?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xmlns:p"http://www.springframework.org/schema/p"x…...
windows环境下安装RabbitMQ
一、RabbitMq简介1.1消息队列中间件简介消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题实现高性能,高可用,可伸缩和最终一致性[架构] 使用较多的消息队列有 ActiveMQ(安全)&#x…...
Java源码规则引擎:jvs-rules决策流的自定义权限控制
规则引擎用于管理和执行业务规则。它提供了一个中央化的机制来定义、管理和执行业务规则,以便根据特定条件自动化决策和行为。规则引擎的核心概念是规则。规则由条件和动作组成。条件定义了规则适用的特定情况或规则触发的条件,而动作定义了规则满足时要…...
Python-字符串的世界
Python字符串的世界 在Python编程中,字符串(String)是一种非常重要的数据类型,用于表示文本信息。字符串可以包含字母、数字、特殊字符以及空格,它们在编程中被广泛用于文本处理、格式化输出、字符串匹配等各种场景。…...
使用上 Spring 的事件机制
本文主要是简单的讲述了Spring的事件机制,基本概念,讲述了事件机制的三要素事件、事件发布、事件监听器。如何实现一个事件机制,应用的场景,搭配Async注解实现异步的操作等等。希望对大家有所帮助。 Spring的事件机制的基本概念 …...
Linux安装QT
//进入qt安装包路径 cd qt安装包路径 //修改权限 sudo chmod x qt-opensource-linux-x64-5.14.2.run //运行qt安装包 sudo ./qt-opensource-linux-x64-5.14.2.run //安装编译器 sudo apt-get install gcc g //安装编译工具 sudo apt-get install build-essential //安装Op…...
如何用arduino uno主板播放自己想要的曲子。《我爱你中国》单片机版本。
目录 一.效果展示 二.基本原理 三.电路图 四.代码 一.效果展示 arduino播放《我爱你中国》 二.基本原理 利用arduino uno单片机实现对蜂鸣器振动频率的调节,基于PWM控制系统通过代码实现控制。 三.电路图 四.代码 //main.uno #define Buzzer 2int PotBuffer …...
redis入门2-命令
Redis的基本数据类型 redis的基本数据类型(value): string,普通字符串 hash(哈希),适合存储对象 list(列表),按照插入顺序排序,可以由重复的元素 set(无序集合),没有重复的元素 sorted set(有序集合)&…...
Typescript 枚举类型
枚举是用来表示一组明确的可选值列表 // enum是枚举类型的关键字 //枚举如果不设置值,默认从0开始 enum Direction {Up, // 0 Down, // 1 Left, // 2Right // 3} //如果给第一个值赋值为100,则第二、第三第四个都会在第一个的基础上1 分别是101,102…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...
针对药品仓库的效期管理问题,如何利用WMS系统“破局”
案例: 某医药分销企业,主要经营各类药品的批发与零售。由于药品的特殊性,效期管理至关重要,但该企业一直面临效期问题的困扰。在未使用WMS系统之前,其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...
