比较循环与迭代器的性能: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.…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...

Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...

AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...