运行时间_一种简单、实用的测量程序运行时间的方法
点击上方「嵌入式大杂烩」,选择「置顶公众号」第一时间查看嵌入式笔记!
前言
平时我们可能很少去关注程序运行的时间,但是在一些情况下可能需要对程序进行一个整体的复盘、优化。
那么,程序运行的时间就是一个可以考虑的方面,可以测一下某些代码块、函数、算法的运行时间,然后整体考虑看看有没有必要进行优化。
之前在某工控类项目中,我就有接到一个任务去测试程序中关键代码的执行时间,并输出报告。当时是使用一个GPIO+示波器
进行测试的,也可以使用逻辑分析仪来测。
当时测量的方法很简单:
在要测试的代码块/函数之前设置该GPIO的电平为高电平,在要测试的代码块/函数之后设置该GPIO为低电平,使用示波器测高电平的时间,就知道了这一代码块/函数的运行时间。
下面就通过实例来介绍一下这种简单而有效的方法。
我这里使用逻辑分析仪来测量,使用小熊派开发板
来验证,小熊派的主控为STM32L431RCT6
,系统时钟设置为80MHz
。
这里顺带提一点题外话,之前有一些初学的读者朋友问我说逻辑分析仪贵不贵。逻辑分析仪有贵的也有便宜的,贵则上千上万元,便宜则有几十、几百。我觉得无论工作、还是学习,都有必要入手一个逻辑分析仪。
本篇笔记的测试用的逻辑分析仪就是某宝上二十几块钱买的,可以满足平时的学习所用。条件有限的学生朋友可以入手。有条件的可以考虑入手几百块钱的。
GPIO+逻辑分析仪测时间
1、测量HAL_Delay函数
STM32的HAL库有给我们提供一个HAL_Delay
延时函数,这是一个ms级延时函数。这个延时函数依赖于系统滴答定时器,所以是一个比较精确的延时函数。
这里,我们就使用GPIO+逻辑分析仪
的方法来测量一下这个延时函数。为了方便测试,我们在while死循环里进行测量。
代码:
测量结果:
可见,我们通过逻辑分析仪测出了HAL_Delay(100);
运行的时间为100.4315ms
,符合我们的预期。
这里高电平两侧其实就是低电平部分,只不过低电平持续的时间太短了,在这里看起来像一条竖线,我们放大来看看:
结果已经很准了,可以满足平时的测量。这种测量很难保证百分之百的精确,小数点后面的那一部分可能是受很多不可控因素的影响,这不在我们本篇文章的讨论范围之内。
我们是想通过这个示例来介绍这种测量方法的使用及证明这种方法是可行的。下面再继续看两个实例。
2、测量软件延时函数
我们以前刚开始学单片机的时候,经常有用到一些粗略的延时函数,其实现方法就是循环执行n条空语句,以达到一个延时的效果。
那么,我们怎么来构造一个us级或ms级的粗略延时函数(软件延时函数)。我们之前看到的粗略延时函数类似这样子:
这些函数里面需要给出一些循环的次数,这个值是怎么来确定的呢?比如上面这个函数中123这个值是怎么来确定的?我们可以使用GPIO+逻辑分析仪的方法
来进行一个简单的确定。
确定1us:
不同的处理器,结果是不一样的。针对小熊派开发板(主控:STM32L431RCT6),循环运行15条空语句的时间实测结果是1.083us
,这算是比较接近1us了。
我们就运用这个结果来构建一个us级软件延时函数如下:
接下来我们测一下soft_delay_us(100);
实际运行了多长时间:
可见,结果差不多接近我们想要的结果。构建这样的粗略延时函数可以使用这样的方式来确定一些循环次数的值。
3、查表法VS常规法运行时间
在之前的文章:空间换时间,查表法的经典例子《空间换时间,查表法的经典例子》中,我们有说可以适当使用查表法降低程序的执行时间。这里我们来实际测量对比一下那篇文章中查表法与常规法的优劣。
关键代码:
/* 测试结果 */struct test_res{ unsigned int data; /* 数据 */ unsigned int count; /* 数据中1的个数 */};
/* ============常规法============ */#if 1struct test_res get_test_res(unsigned int data){ /* 保存测试结果 */ struct test_res res;
/* 保证数据总会在0~0xf之间 */ // unsigned int temp = data & 0xf; unsigned int temp = data & 0xff;
res.count = 0; res.data = temp;
/* 循环判断每一位 */ for (int i = 0; i 16; i++) { if (temp & 0x01) { res.count++; } temp >>= 1; }
return res;}#else/* ============查表法============ */
int table[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
struct test_res get_test_res(unsigned int data){ /* 保存测试结果 */ struct test_res res;
/* 保证数据总会在0~0xf之间 */ unsigned int temp = data & 0xff;
/* 获取低4位中1的个数 */ unsigned int low_data = temp & 0xf; unsigned int low_cnt = table[low_data];
/* 获取高4位中1的个数 */ unsigned int high_data = (temp >> 4) & 0xf; unsigned int high_cnt = table[high_data];
/* 结果 */ res.count = low_cnt + high_cnt; res.data = temp;
return res;}
int main(void){ /* USER CODE BEGIN 1 */ struct test_res res = {0};
/* 省略部分代码。。。。。。。。。 */
while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); res = get_test_res(30); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); } /* USER CODE END 3 */}#endif
常规法程序的运行时间:
查表法程序的运行时间:
可见,这个例子中常规法程序运行时间约为2ns,而查表法程序运行时间约为500ns。查表法的程序运行之间仅为常规法的1/4,省下了3/4的时间。
随着调用次数的增多,这里的查表法的优势越大。比如循环计算0~31这32个数中每一个数二进制位为1的个数,则相关代码改为:
int i; while (1) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); for (i = 0; i 32; i++) { res = get_test_res(i); } HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); }
常规法:
查表法:
可见,随着调用次数的增多,查表法相对于常规法更省时,即查表法的优势越大。
以上就是关于GPIO+逻辑分析仪测程序运行时间
的几个实例。下面顺带提一下使用MDK+ST-LINK
测STM32程序运行时间的方法。
MDK+ST-LINK测时间
在使用MDK作为开发工具时,可以搭配一些仿真器来查看程序执行时间。这里通过实例来介绍MDK+ST-LINK
测STM32程序运行时间的方法。
这里重点是设置Trace
里面的系统内核时钟,我们这里使用的是小熊派开发板(主控:STM32L431RCT6),并且配置的系统时钟是80MHz:
所以在Trace
中要设置为80MHz。这个得根据实际芯片的型号就需要根据进行修改,比如STM32F103系列默认是72MHz,STM32F429系列默认为180MHz等,根据实际进行修改。
下面我们通过在线调试、打断点的方式看一下 HAL_Delay(1000);
运行了多长时间:
可见程序运行到HAL_Delay(1000);
前后的时间分别为:
前:0.00008964s后:1.00108161s
即HAL_Delay(1000);
走过的时间约为1s,符合预期。
最后
以上就是本次的实践分享,感谢阅读与支持。如有错误,欢迎指出。谢谢!
若觉得文章不错,转发分享、在看,也是我们继续更新的动力。
在公众号内回复更多资源,可免费获取嵌入式资料。期待你的关注~
猜你喜欢
C语言、嵌入式应用:TCP通信实例分析
一些不可不知的计算机网络基础
AT指令测试ESP8266通信模组并获取天气数据
在SRAM、FLASH中调试代码的配置方法
STM32串口IAP分享
运行时间_一种简单、实用的测量程序运行时间的方法相关推荐
- 一种简单、实用的测量程序运行时间的方法
前言 平时我们可能很少去关注程序运行的时间,但是在一些情况下可能需要对程序进行一个整体的复盘.优化. 那么,程序运行的时间就是一个可以考虑的方面,可以测一下某些代码块.函数.算法的运行时间,然后整体考 ...
- 一种简单实用的全屏方法
实现程序全屏幕显示的思路有很多种,最常见的一种就是: 1)利用Windows API提供的一个结构体WINDOWPLACEMENT来存储全屏显示前视图和主框架窗口在屏幕上的位置和显示信息.非客户区窗口 ...
- 抠图软件哪种好用?试试这几种简单实用的抠图工具
当我们在制作人物照片时,需要将人物抠出来,然后放置在不同的背景上,以达到不同的艺术效果.抠图可以让人物照片更加独特.美观,吸引更多的关注和欣赏.此外,有时候一张照片中会有一些瑕疵或者不需要的物品,需要 ...
- 录屏软件有哪些?分享几种简单实用的录屏工具
有哪些好用的录屏软件呢?如果你需要向他人展示如何操作一个软件或者如何进行某项任务,录制一个演示视频是非常有用的.你可以在视频中演示每个步骤,然后分享给你的观众.这对于教育和培训领域非常有用,因为它可以 ...
- ICCV2021 Oral SimROD:简单高效的数据增强!华为提出了一种简单的鲁棒目标检测自适应方法...
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨小马 来源丨我爱计算机视觉 ▊ 写在前面 本文提出了一种简单有效的鲁棒目标检测无监督自适应方法( ...
- 如何测量程序运行时间?
整理:黄工 素材来源:最后一个Bug 程序的运行时间,对一个系统比较重要.有的地方要求精确延时Nus,有的地方要求程序运行时间不能超过Nus. 所以,今天给大家分享一些常见测量程序(任务)运行时间的方 ...
- 测量程序运行时间的几个函数
摘要:本文详细的讨论了在windows平台中,测量程序运行时间的几个函数,GetTickCount, QueryPerformanceCounter和RDTSC,并给出示例代码. 算法的好坏有好多评价 ...
- sql 拼接int类型的字段_一套简单实用的SQL脚本(下篇)
点击上方SQL数据库开发,关注获取SQL视频教程 SQL专栏 SQL数据库基础知识汇总 SQL数据库高级知识汇总 之前已经分享了一部分内容<一套简单实用的SQL脚本(上篇)>接上一章我们继 ...
- jQuery的几种简单实用效果
许久未分享博客,或许已生疏. 闲来无事, 分享几个jQuery简单实用的效果案例 不喜勿喷... 1.页面常用的返回顶部 <!DOCTYPE html> <html lang=&qu ...
最新文章
- linux之/usr/local/bin和/usr/bin区别
- 金笛MODEM池 (RS232串口和RJ45网口)
- Oracle 游标示例,带异常处理
- 探索Spring异步代理循环依赖失败的问题
- C# SqlParameter 里面使用 LIKE % 模糊查询
- Small Basic 语言 学习笔记
- ps怎么给人物抠图教程详细图解
- 分析图书管理系统的5W1H
- linux shc shell脚本_用shc加密shell脚本
- c++实现多对多生产者消费者和socket连用
- elementUI中el-table树形与el-tree树形结构的一键折叠与展开
- 从PLC ,PAC ,到施耐德的自动化开放系统
- CalendarPicker
- ICML 2022|达摩院多模态模型OFA,实现模态、任务和架构三个统一
- 删除文件后清空了回收站要怎么恢复
- 乙腈和水共沸_常用有机溶剂共沸点
- (机器学习周志华 西瓜书 南瓜书)吃瓜教程 Task01
- modeller建模
- 康宁杰瑞、君实生物、天境生物人事任命;赛诺菲诺维乐在中国上市新适应证 | 医药健闻...
- 博士招生|美国Rutgers University牛思淼课题组招收2023年秋季入学的全奖博士生
热门文章
- 在Python中为什么切片要忽略最后一个元素?
- Python基础教程:对象及数字对象与数学运算
- Python基础教程:列表解析
- python多进程编程常用到的方法
- m5310采用芯片 中移物联_联想首发瑞芯微最新智能物联芯片产品
- java 连接janusgraph_基于JanusGraph的大数据图数据库
- C语言用数组(顺序表)实现大小固定的队列的方法
- c语言项目为什么要build?(gcc、makefile、cmake(qmake)、CMakeLists.txt)(qmake、cmake、qbs区别解析)(qmake还是cmake,mingw作用)
- python如何拟合三维平面(拟合Intel Realsense D435深度数据点)
- python 文件操作 os.readline()函数用法