同事用“与运算“改了这几行代码,运行效率直接起飞~


正文


大家好,我是bug菌~

1

问题背景

最近由于项目指标的需求,查了下程序各个部分的运行效率,发现一直用的环形缓冲区在耗时占比中还挺突出,于是过了一遍代码并尝试着去优化一下,没想到改动不大却得到了较大的效率提升。

如下是之前环形缓冲区的一些代码片段:

#define BUFFER_SIZE 512 uint16_t buffer[BUFFER_SIZE]; uint16_t index = 0; ...... index = (index + 1) % BUFFER_SIZE; ......

当程序高频率的调用含有取模的运算接口时执行时间超出了设计预期,同时在低优化等级(毕竟如果编译器进行了各种优化,那就不好聊下去了)下对取模运算进行了相关sysclock的测量,确实也是效率不高,于是我打算用更高效的运算方式把它替换掉。

2

与运算代替取模

当然了,与运算至少全面替代取模运算没那么容易,毕竟如果能够完全替代,也不会有人用取模了,当时对于嵌入式行业我觉得最有意思的是它并不需要非常的通用,嵌入式只需要在特定的领域,特定的工况下能做到极致就可以了,有取舍才能在有限的资源下把平台充分利用起来。

同样的思路取模运算确实很强大,但是我并不需要利用它所覆盖的方方面面,所以当除数是2的幂(即n = 2^k)时,与运算同样可以满足我的需求:

// 当 n 是 2 的幂(n = 2^k)时 a % n = a & (n - 1) // 等价的情况(n是2的幂) a % 8 == a & 7 // 8 = 2^3 a % 16 == a & 15 // 16 = 2^4 a % 32 == a & 31 // 32 = 2^5

我们知道% 运算通常需要除法指令,开销较大,而& 运算只需要按位与,速度快很多。

所以对应环形缓存区只需要优化下:

#define BUFFER_SIZE 512 // 必须为2的幂 #define BUFFER_MASK (BUFFER_SIZE - 1) // 511 = 0x1FF uint16_t buffer[BUFFER_SIZE]; uint16_t index = 0; ...... index = (index + 1) & BUFFER_MASK; // 快速回绕 ......

3

再细致一点

聊到这里,来龙去脉应该讲清楚了,其实不管了是在这一次的环形缓存区的优化中有所感悟这种方法,只要是在当除数是2的幂时这种方式都能大大提高效率,特别是一些实时性应用场景,一通百通。

比如说你要进行ADC窗口滑动:

samples[sample_index] = adc_read(); ...... // sample_index = (sample_index + 1) % WINDOW_SIZE; //直接方式 sample_index = (sample_index + 1) & WINDOW_MASK; ......

一些限制和风险我们也要非常有数,一些bug大部分都是因为我们没有提前想到:

1、在性能关键路径且除数是2的幂时,才考虑使用与运算替代取模运算,其他地方其实无关痛痒也没必要替换,所以可以做一些防御性检测:

#ifndef IS_POWER_OF_TWO #define IS_POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0) #endif #define QUEUE_SIZE 128 #if !IS_POWER_OF_TWO(QUEUE_SIZE) #error "QUEUE_SIZE must be power of two for optimization" #endif #define QUEUE_MASK (QUEUE_SIZE - 1)

2、如果是处理负数大概率会出问题,要留意。

最后

好了,今天就跟大家分享这么多了,如果你觉得有所收获,一定记得点个~

唯一、永久、免费嵌入式技术知识分享平台

推荐专辑 点击蓝色字体即可跳转

MCU进阶专辑

嵌入式C语言进阶专辑

“bug说”专辑

专辑|Linux应用程序编程大全

专辑|学点网络知识

专辑|手撕C语言

专辑|手撕C++语言

专辑|经验分享

专辑|电能控制技术

专辑 | 从单片机到Linux

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1188719.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 环境配置(详细教程)

Java 环境配置详细教程(2025–2026 最新主流方式) 以下教程主要针对 Windows、macOS、Linux(Ubuntu/Debian/CentOS) 三种主流操作系统,2025–2026 年最推荐的配置方式。 目前(2026年初)最推荐…

深入 TCP 核心:握手、挥手、滑动窗口与并发服务器实战

一、 连接的诞生与消亡 1. 三次握手 (The 3-Way Handshake) 发生时机:connect() 调用时。 本质:双方确认对方的发送和接收能力正常,并同步初始序列号 (ISN)。 第一次:客户端发送 SYN=1, seq=J。(我想连你) 第二次:服务器回复 SYN=1, ACK=1, ack=J+1, seq=K。(收到,我…

不仅仅是浏览器渲染:揭秘 Botasaurus 高效的 HTTP 请求封装

在现代网页爬虫与自动化领域,开发者常常面临一个“鱼与熊掌不可兼得”的困境:使用 Headless 浏览器(如 Playwright 或 Selenium)虽然能轻松应对复杂的 JavaScript 渲染和反爬校验,但资源消耗巨大、速度缓慢&#xff1b…

10个秘密:软件开发者的晋升路径大揭秘

测试从业者的职业晋升新视角 在软件开发生态中,测试从业者常被视为质量守护者,但晋升路径往往模糊不清。本文揭秘10个关键策略,帮助测试工程师突破职业瓶颈,从技术深耕到管理跃迁,实现可持续发展。这些秘密融合行业洞…

如何打开命令提示符

在 Windows 系统(包括 Windows 10、Windows 11 和 Windows 11 的最新更新版本)中,打开命令提示符(Command Prompt,简称 CMD)有多种常用方法。下面列出最实用、最快的几种方式,从最推荐开始排序&…

网络安全学习路线图:从零基础到全栈工程师

网络安全学习路线图:从零基础到全栈工程师 “看了 3 个月网络安全教程,学了 TCP/IP、防火墙原理,却连‘怎么用 Nmap 扫一个端口’都不会;跟着视频做了 DVWA 漏洞复现,换个靶场就一脸懵;不知道该先学 Web 渗…

如何避免职业倦怠:软件测试工程师的终极自救手册

倦怠危机的行业特殊性 在敏捷开发与持续交付的行业背景下,软件测试工程师面临版本迭代加速、需求变更频繁、质量责任高压三重挑战。2025年行业调研显示,78%的测试从业者存在中度以上倦怠感,其中自动化脚本维护、跨部门协作摩擦、技术迭代焦虑…

nginx的JavaScript魔力:njs简介与实践

Nginx 的 JavaScript 魔力:njs 简介与实践(2026 年视角) njs(NGINX JavaScript module)是 NGINX 官方推出的动态模块,让你可以用 JavaScript(ECMAScript 5.1 严格模式 部分 ES6 扩展&#xff…

网络安全学习路线图(2026版详解)

近期,大家在网上对于网络安全讨论比较多,想要学习的人也不少,但是需要学习哪些内容,按照什么顺序去学习呢?其实我们已经出国多版本的网络安全学习路线图,一直以来效果也比较不错,本次我们针对市…

(3-1)机器人身体结构与人体仿生学:人体生物力学与关节分析

本章内容围绕人形机器人身体结构与人体仿生学展开,系统分析了人体生物力学特征及其对机器人结构设计的指导意义。首先从关节自由度、运动范围与扭矩需求入手,结合力臂与质量分布,阐明人体动态平衡的力学基础;随后重点介绍了人形机…

建站知识:域名/ 空间/ IP/ 端口之间的关系

域名、空间、IP、端口之间的关系(建站完整图解,2026 年视角) 建站最基础的四要素就是这四个:域名、空间(服务器/主机)、IP 地址、端口。它们的关系可以用一句话概括: 域名 → 解析到 → IP地址…

【全网最全】网络安全自学路线图:从零到专家,附资源清单与避坑指南

只要你敢学我就敢教!500集黑客入狱教程,从入门到入狱!全程干货无废话,学不会我退网! 学习路线图 第一阶段:基础奠基(约2-3个月) 首先需要建立坚实的基础知识,这是后续…

2026年职业蓝图:从码农到CTO的加速计划

软件测试从业者的独特优势与CTO之路‌ 在数字化转型浪潮中,软件测试从业者常被视为技术生态的“守门人”,但2026年的科技革命(如AI与DevOps普及)正重塑职业格局。测试工程师凭借对质量、风险与系统的深刻理解,拥有晋升…

耐达讯自动化Profibus总线光纤中继器在连接测距仪中的应用

在工业自动化领域,实时、可靠的数据传输是确保生产效率和系统稳定性的核心要素。Profibus协议作为主流的工业通信标准,在各类自动化设备中广泛应用。然而,面对长距离传输、电磁干扰等复杂工况,传统电缆传输的局限性逐渐凸显。耐达…

精:C# 的四种委托实现详解

一、什么是委托1.1 官方解释委托是一种定义方法签名的类型。当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联,并通过委托实例调用该方法。1.2 个人理解委托就是用于封装和执行方法(函数)的一个类。★事件是一种特殊…

国产DevSecOps工具崛起:安全左移战略下的技术创新与市场重构

国产DevSecOps工具崛起:安全左移战略下的技术创新与市场重构 随着数字化转型进入深水区,软件开发的安全需求正在发生根本性变革。Gartner最新预测显示,到2025年中国DevSecOps工具市场将突破78亿元规模,年复合增长率高达42%&#x…

震惊!90%的AI从业者忽略了这些职业发展技巧

AI浪潮下的测试职业警钟 在2026年的今天,人工智能(AI)已渗透到软件开发的每个角落,但一个令人震惊的数据浮出水面:90%的AI从业者——包括开发者、数据科学家和测试工程师——忽视了关键的职业发展技巧。尤其对于软件测…

耐达讯自动化Profibus总线光纤中继器:光伏逆变器通讯的“稳定纽带”

在光伏发电系统中,实时数据采集与精准控制是保障发电效率与系统安全的核心。光伏逆变器作为能量转换的关键设备,其运行状态需与中央控制系统实时交互。然而,传统Profibus总线在长距离、强干扰环境下易出现信号衰减或中断。耐达讯自动化Profib…

‌软件测试员如何年薪翻倍的5个策略

在当今竞争激烈的软件测试行业,薪资增长已成为从业者关注的核心议题。随着技术迭代加速和企业对质量要求的提升,软件测试员面临双重挑战:一方面,自动化与AI的普及可能挤压基础测试岗位;另一方面,具备高阶技…

多商户+多端一体化:商城系统的核心功能架构与源码实现

温馨提示:文末有资源获取方式寻找一款既能自主创业,又能开启技术服务业务的电商系统?您的需求,现在有了完美的答案。我们为您带来一款经过重磅升级、功能堪称豪华的多端多商户商城源码,它专为有远见的创业者与开发者设…