比较循环与迭代器的性能:Rust 零成本抽象的威力
一、引言
在早期的 I/O 项目中,我们通过对 String 切片的索引和 clone 操作来构造配置结构体,这种方法虽然能确保数据所有权的正确传递,但既显得冗长,又引入了不必要的内存分配。随着对 Rust 迭代器特性的深入了解,我们可以通过直接传递 env::args 返回的迭代器、利用 next 方法和迭代器适配器(如 filter、map、collect)重构代码,使代码表达更明确、逻辑更清晰,同时保持高性能。
二、循环 vs. 迭代器:性能对比
2.1 Benchmark 结果
为了比较两种实现方式的性能,我们对 search 函数进行了基准测试。测试中,我们将《福尔摩斯探案全集》的全部内容加载到一个 String 中,并搜索其中的单词 “the”。以下是使用显式 for 循环和迭代器实现的 search 函数的基准测试结果:
test bench_search_for ... bench: 19,620,300 ns/iter (+/- 915,700)
test bench_search_iter ... bench: 19,234,900 ns/iter (+/- 657,200)
可以看出,两种实现方式的性能几乎相当。这表明尽管迭代器是一种高层次抽象,但编译器会将其优化成与手写循环相似的高效代码,从而实现所谓的零成本抽象。
三、零成本抽象:迭代器的优化原理
Rust 设计迭代器时的目标就是实现零成本抽象。也就是说,使用迭代器这种高层抽象并不会带来额外的运行时开销,编译器会将这些抽象优化为与手动编写的低级循环代码无异的高效机器码。
3.1 迭代器适配器与闭包
例如,在 search 函数中,我们可以将原本依赖可变向量的循环重构为:
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {contents.lines() // 创建一个行迭代器.filter(|line| line.contains(query)) // 使用闭包过滤包含查询词的行.collect() // 将结果收集到 Vec 中
}
这种写法使用了 filter 和 collect 适配器,闭包在内部完成判断逻辑。编译器能够将这些高层次操作内联和优化,消除闭包调用的开销。
3.2 循环展开与寄存器分配
更进一步看一个真实世界的例子,在音频解码器中,我们需要利用线性预测算法来计算未来的采样值。下面的代码使用了迭代器链:
let buffer: &mut [i32];
let coefficients: [i64; 12];
let qlp_shift: i16;for i in 12..buffer.len() {let prediction = coefficients.iter().zip(&buffer[i - 12..i]).map(|(&c, &s)| c * s as i64).sum::<i64>() >> qlp_shift;let delta = buffer[i];buffer[i] = prediction as i32 + delta;
}
在这段代码中,编译器知道循环迭代次数固定为 12 次,因此会对循环进行展开,将迭代器链转化为重复的内联代码,并将所有系数存储在寄存器中,从而消除了运行时的边界检查和循环控制开销。正是这些优化证明了迭代器虽然表达上高层,但实际运行时和手写低级循环无异,确保了零成本抽象。
四、实战示例:音频解码器中的迭代器链
在音频解码的场景中,高效的数据处理至关重要。上述代码片段展示了如何利用 zip、map 和 sum 三个迭代器适配器来实现线性预测计算。具体步骤如下:
coefficients.iter():创建一个对系数数组的迭代器。zip(&buffer[i - 12..i]):将系数与之前 12 个采样值配对。map(|(&c, &s)| c * s as i64):对每对值进行乘法计算,注意类型转换。sum::<i64>():将所有乘积求和,得到预测值。- 右移
qlp_shift位:完成预测结果的位移操作。
这种链式操作不仅简洁明了,而且编译器能将其优化到和手写循环相同的效率,非常适合对性能要求极高的应用场景。
五、总结
通过以上讨论,我们可以得出以下几点结论:
- 高层抽象与低成本实现:Rust 的迭代器和闭包设计使得开发者可以用简洁的代码表达复杂逻辑,而编译器会将这些抽象优化为与手写低级代码相当的高效实现。
- 性能无额外开销:基准测试表明,使用迭代器实现的
search函数与使用for循环的版本性能基本一致,证明了 Rust 的零成本抽象理念。 - 实际应用中的优势:从 I/O 项目到音频解码器,迭代器不仅提高了代码的可读性和可维护性,同时也为未来的并行优化和代码改进提供了良好的基础。
Rust 通过提供强大的迭代器和闭包,使得我们能以高层次方式表达逻辑,同时不牺牲性能。这种设计理念不仅提高了开发效率,还为构建高性能系统奠定了坚实的基础。接下来,你可以继续探索 cargo 的更多功能,将你的项目分享给全世界,共同享受 Rust 带来的强大生产力。
相关文章:
比较循环与迭代器的性能:Rust 零成本抽象的威力
一、引言 在早期的 I/O 项目中,我们通过对 String 切片的索引和 clone 操作来构造配置结构体,这种方法虽然能确保数据所有权的正确传递,但既显得冗长,又引入了不必要的内存分配。随着对 Rust 迭代器特性的深入了解,我…...
一文了解zookeeper
1.ZooKeeper是什么 简单来说,她是一个分布式的,开放源码的分布式应用程序协调服务 具体来说,他可以做如下事情: 分布式配置管理:ZooKeeper可以存储配置信息,应用程序可以动态读取配置信息。分布式同步&a…...
算法题(67):最长连续序列
审题: 需要我们在O(n)的时间复杂度下找到最长的连续序列长度 思路: 我们可以用两层for循环: 第一层是依次对每个数据遍历,让他们当序列的首元素。 第二层是访问除了该元素的其他元素 但是此时时间复杂度来到…...
大中型企业专用数据安全系统 | 天锐蓝盾终端安全 数据安全
天锐蓝盾系列产品是专门为大中型企业量身定制的数据安全防护产品体系,涵盖天锐蓝盾DLP、天锐蓝盾终端安全管理系统、天锐蓝盾NAC以及其他搭配产品,致力于实现卓越的数据安全防护、施行严格的网络准入控制以及构建稳固的终端安全管理体系。通过全方位的防…...
Deepseek解读 | UE像素流送与实时云渲染技术的差别
为了实现UE引擎开发的3D/XR程序推流,绝大多数开发者会研究像素流送(Pixel Streaming)的使用方法,并尝试将插件集成在程序中。对于短时、少并发、演示场景而言,像素流送可以满足基本需求。当3D/XR项目进入落地交付周期后…...
CTFSHOW-WEB入门-PHP特性109-115
题目:web 109 1. 题目: 2. 解题思路:题目要求获得两个参数,v1 v2,if语句中的意思是要求两个参数都包含字母,条件满足的话,执行 echo new 类名(方法()…...
模糊综合评价法:原理、步骤与MATLAB实现
引言 在复杂决策场景中,评价对象往往涉及多个相互关联的模糊因素。模糊综合评价法通过建立模糊关系矩阵,结合权重分配与合成算子,实现对多因素系统的科学评价。本文详细讲解模糊综合评价法的数学原理、操作步骤,并辅以MATLAB代码…...
【数据结构-红黑树】
文章目录 红黑树红黑树介绍红黑树的五个基本性质红黑树的平衡原理红黑树的操作红黑树的操作 代码实现节点实现插入和查询操作 红黑树 红黑树介绍 红黑树(Red-Black Tree)是一种自平衡的二叉查找树(Binary Search Tree, BST)&…...
【STM32】舵机SG90
1.舵机原理 舵机内部有一个电位器,当转轴随电机旋转,电位器的电压会发生改变,电压会带动转一定的角度,舵机中的控制板就会电位器输出的电压所代表的角度,与输入的PWM所代表的角度进行比较,从而得出一个旋转…...
【Linux】Socket编程—TCP
🔥 个人主页:大耳朵土土垚 🔥 所属专栏:Linux系统编程 这里将会不定期更新有关Linux的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉 文章目…...
c++11 for auto不定参数
数量不定的模板参数。参数分为一个和一包两部分。 冒号的左边声明一个变量。右手边必须是一个容器。从容器(某种数据结构)中找出每一个元素设置到左边这个变量。11之前可以用容器的迭代器去取数据。或者标准库里的foreach...
C#+redis实现消息队列的发布订阅功能
代码 参考c#redis stream实现消息队列以及ack机制文章的思路,实现 SubscribeAttribute.cs using System;namespace DotnetQueue.Attributes {/// <summary>/// 订阅特性/// </summary>[AttributeUsage(AttributeTargets.Method, Inherited false)]pu…...
Docker容器基本操作
容器的基本操作 操作命令(全)命令(简)容器的创建docker container run <image name>docker run <image name>容器的列出(up)docker container lsdocker ps容器的列出(up和exit&…...
从无序到有序:上北智信通过深度数据分析改善会议室资源配置
当前企业普遍面临会议室资源管理难题,预约机制不完善和临时会议多导致资源调度不合理,既有空置又有过度拥挤现象。 针对上述问题,上北智信采用了专业数据分析手段,巧妙融合楼层平面图、环形图、折线图和柱形图等多种可视化工具&a…...
总结:使用JDK原生HttpsURLConnection,封装HttpsUtil工具类,加载自定义证书验证,忽略ssl证书验证
总结:使用JDK原生HttpsURLConnection,封装HttpsUtil工具类,加载自定义证书验证,忽略ssl证书验证 一HttpsUtil工具类二SSLUtil工具类 一HttpsUtil工具类 package com.example.util;import javax.net.ssl.HttpsURLConnection; impo…...
重新定义人机关系边界,Soul以AI社交构建多元社交元宇宙
近年来,AI Native应用的兴起已逐渐成为大众关注的焦点。在此背景下,Soul App的首席技术官陶明在极客公园IF2025创新大会上,发表了一场主题为“人机关系的新边界,Soul如何定义AI社交未来”的演讲。他分享了Soul在人工智能领域内的最新技术进展和战略规划,同时也将Soul社交元宇宙…...
HTTP 参数污染(HPP)详解
1. 什么是 HTTP 参数污染(HPP)? HTTP 参数污染(HTTP Parameter Pollution,简称 HPP)是一种 Web 应用攻击技术,攻击者通过在 HTTP 请求中注入多个相同的参数来绕过安全控制或篡改应用逻辑&#…...
阿里云轻量服务器docker部署nginx
拉取nginx docker镜像 sudo docker pull nginx创建以下挂载目录及文件 用户目录下:conf html logs conf: conf.d nginx.conf html: index.html conf.d: default.confnginx.conf添加文件内容 events {worker_connections 1024; }http {include /etc/ngi…...
(萌新入门)如何从起步阶段开始学习STM32 —— 我应该学习HAL库还是寄存器库?
概念 笔者下面需要介绍的是库寄存器和HAL库两个重要的概念,在各位看完之后,需要决定自己的学习路线到底是学习HAL呢?还是寄存器呢?还是两者都学习呢? 库寄存器 库寄存器就是简单的封装了我们对寄存器的操作…...
Windchill开发-电子仓相关对象信息查询SQL
电子仓相关对象信息查询SQL 一、说明二、数据表信息三、数据表字段说明3.1 HOLDERTOCONTENT3.1.1 对象类型3.1.2 存储类型 3.2 APPLICATIONDATA3.2.1 类别3.2.2 与对象的角色关系3.2.3 存储方式3.2.4 其他字段 3.3 URLDATA3.4 STREAMDATA3.5 FVITEM3.6 FVMOUNT3.6.1 安装状态3.…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
