c程序杂谈系列(职责链模式与if_else)

从处理器的角度来说,条件分支会导致指令流水线的中断,所以控制语句需要严格保存状态,因为处理器是很难直接进行逻辑判断的,有可能它会执行一段时间,发现出错后再返回,也有可能通过延时等手段完成控制流的正确性。所以笔者在想,使用过多的if _else,除了可读性差,是否还会对执行效率造成影响呢?

于是笔者决定采用职责链重构if控制语句,笔者猜想,如果采用设计模式既可以避免if分支,提高执行效率,同时可以让程序具备解耦合性和可维护性,是否是一种更优解呢?

为了验证笔者的猜想,更好的优化c语言程序,笔者使用职责链模式对一段if_else程序进行了重构。

程序的性能标准是执行时间,计算程序时间的程序来源于:C语言 计算程序运行时间(精确到毫秒/微秒)_c语言计算运行时间-CSDN博客

以下是笔者本人用c编写的责任链设计模式:

#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<string.h>
#include <windows.h>typedef int (*Handler)(int);typedef struct task_node
{Handler handler;struct task_node* next;
}taskN;int task1(int a) {if (a == 1) {//printf("a == 1"); printf会耗费大量时间,为了不影响测试,所以只留下判断语句return 0;}return -1;
}int task2(int a) {if (a == 2) {return 0;}return -1;
}int task3(int a) {if (a == 3) {return 0;}return -1;
}int task4(int a) {if (a == 4) {return 0;}return -1;
}int task5(int a) {if (a == 5) {return 0;}return -1;
}int task6(int a) {if (a == 6) {return 0;}return -1;
}int task7(int a) {if (a == 7) {return 0;}return -1;
}int task8(int a) {if (a == 8) {return 0;}return -1;
}int task9(int a) {if (a == 9) {return 0;}return -1;
}int task10(int a) {if (a == 10) {return 0;}return -1;
}int task11(int a) {if (a == 11) {return 0;}return -1;
}int task12(int a) {if (a == 12) {return 0;}return -1;
}taskN* initi() {taskN* tas1 = malloc(sizeof(taskN));taskN* tas2 = malloc(sizeof(taskN));taskN* tas3 = malloc(sizeof(taskN));taskN* tas4 = malloc(sizeof(taskN));taskN* tas5 = malloc(sizeof(taskN));taskN* tas6 = malloc(sizeof(taskN));taskN* tas7 = malloc(sizeof(taskN));taskN* tas8 = malloc(sizeof(taskN));taskN* tas9 = malloc(sizeof(taskN));taskN* tas10 = malloc(sizeof(taskN));taskN* tas11= malloc(sizeof(taskN));taskN* tas12= malloc(sizeof(taskN));tas1->handler = task1;tas2->handler = task2;tas3->handler = task3;tas4->handler = task4;tas5->handler = task5;tas6->handler = task6;tas7->handler = task7;tas8->handler = task8;tas9->handler = task9;tas10->handler = task10;tas11->handler = task11;tas12->handler = task12;tas1->next = tas2;tas2->next = tas3;tas3->next = tas4;tas4->next = tas5;tas5->next = tas6;tas6->next = tas7;tas7->next = tas8;tas8->next = tas9;tas9->next = tas10;tas10->next = tas11;tas11->next = tas12;return tas1;}void process(taskN* bol, int a) {int i = bol->handler(a);while (i != 0){i = bol->handler(a);bol = bol->next;}
}void main() {double run_time;LARGE_INTEGER time_start;	//开始时间LARGE_INTEGER time_over;	//结束时间double dqFreq;		//计时器频率LARGE_INTEGER f;	//计时器频率QueryPerformanceFrequency(&f);dqFreq = (double)f.QuadPart;QueryPerformanceCounter(&time_start);taskN* bol = initi();int a = 12;for (int i = 0; i <= 50000000; i++){/*if (a == 1) {}else if (a == 2) {}else if (a == 3) {}else if (a == 4) {}else if (a == 5) {}else if (a == 6) {}else if (a == 7) {}else if (a == 8) {}else if (a == 9) {}else if (a == 10) {}else if (a == 11) {}else if (a == 12) {}else {}*//*process(bol, a);*/switch (a) {case 1:break;case 2:break;case 3:break;case 4:break;case 5:break;case 6:break;case 7:break;case 8:break;case 9:break;case 10:break;case 11:break;case 12:break;default:break;}}QueryPerformanceCounter(&time_over);	//计时结束run_time = 1000000 * (time_over.QuadPart - time_start.QuadPart) / dqFreq;//乘以1000000把单位由秒化为微秒,精度为1000 000/(cpu主频)微秒printf("\nrun_time:%fus\n", run_time);/*为了偷懒,程序就懒得free了*/}

使用if_else时:

a=1,第一个循环执行:

a=12,最后一个循环执行:

两者时间基本没区别,在循环语句中

笔者还测试了只有if( a== 1)这一个判断语句下的性能:

可以看出基本没什么区别。

使用case时:

a=12时如下,与a=1时的结果几乎没有区别:

switch语句除了比较简洁一点,执行速度完全没法比。

 使用责任链时:

任务优先级在责任链上过高(a=1):

 任务优先级在责任链过低(a=12):

可以看出,职责链的速度非常慢,特别是任务优先级低时,执行速度几乎是if_else的150倍。

综上得出,if_else的执行速度是最快的,如果判断的时间复杂度过大,而且判断语句的数量较少,使用if_else,性能可能会更好。

但是,上述的前提是建立在判断语句的数量较少的情况下。

现在让我们考虑这样一种情况:不是判断a从1到12,而是从a到10000呢?程序等价于下图:

再附加一个条件,大多数情况下,a的值都是1。

虽然if_else的耗时比较短,但是在大量的循环下,耗时也不容小觑。因为a大多数情况是1,其他的判断分支只有小概率发生,此时我们使用责任链就可以完美跳过这些语句的判断:

(程序用for循环表示中间的分支,写得不准确,理解意思就好)

当然,读者可能认为if else if在这里也可以跳过中间的语句,也能实现优先级,但是如果改成这样呢:

这种情况下,if else if只能执行其中一个,显然不行,使用大量的if,就变成了上面的情况,我们不得不将原先的代码大量删除并重写,这十分让人难受。这样一对比,对于部分实现的if分支,使用责任链的优点有什么呢?如下图:

在责任链任务里进行改动,可以选择责任链终止的位置,跳过后面的任务,当然,通过goto等跳转指令也是可以实现的,但是if语句很难做到这样灵活,对于复杂的业务场景,很难在原先的基础上进行拓展,责任链的解耦合性和可拓展性是非常好的优点。

考虑复杂的业务场景,责任链明显优于传统的if_else。

尽管如此,if_else还是十分友好的,特别是在mcu等产品的开发中,使用设计模式的资源花费简直是奢求,毕竟设计模式是针对高级语言的,大多数情况下if_else往往是最优解。不过,笔者认为大量使用if_else的前提是项目不需要长期维护,一般情况下还是要多使用设计模式,例如在linux内核中就有源码使用了责任链模式,这是从性能,解耦合性和可读性等多方面考虑,值得开发者学习。如果是小型项目,对维护没有要求,而且控制语句的数量较少,为了性能和简便性可以考虑直接使用if_else分支。但是如果大型项目中含有大量if分支,可以考虑使用设计模式重构。

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

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

相关文章

【C++/STL】:哈希 -- 线性探测哈希桶

目录 &#x1f4a1;前言一&#xff0c;unordered系列容器二&#xff0c;哈希2.1 哈希的概念2.2 哈希函数2.3 哈希冲突 三&#xff0c;哈希冲突解决(重点)3.1 开放定址法3.2 哈希桶(重点) 四&#xff0c;线性探测的实现4.1 线性探测的基本框架4.2 插入操作4.3 查找操作4.4 删除操…

Let‘s Encrypt

启动Https,需要从证书授权机构(简称CA)处获取一个证书,Lets Encrypt就是一个CA Lets Encrypt上可以获得免费的ssl证书,时间是3个越 下面通过Nginx和Lets Encrypt让网站升级到HTTPS Certbot简介 Certbot是Lets Encrypt官方推荐的获取证书的客户端 Centos 7.9操作 yum install …

openai版本不适配问题(在windows系统下openai migrate)

问题如下&#xff1a; 方法&#xff1a; 参考官网v1.0.0 Migration Guide openai/openai-python Discussion #742 GitHub 具体步骤&#xff1a; 1、curl -fsSL https://docs.grit.io/install | bash -x 但该命令可能不好用————将‘curl -fsSL https://docs.grit.io/i…

谷歌AI拿下IMO奥数银牌,数学推理模型AlphaProof面世,强化学习 is so back

用上了 Gemini 大模型与 AlphaZero 强化学习算法,几何、代数、数论全都会。 对于 AI 来说,奥数不再是问题了。 本周四,谷歌 DeepMind 的人工智能完成了一项壮举:用 AI 做出了今年国际数学奥林匹克竞赛 IMO 的真题,并且距拿金牌仅一步之遥。 上周刚刚结束的 IMO 竞赛共有…

深入分析 Android ContentProvider (九)

文章目录 深入分析 Android ContentProvider (九)ContentProvider 的高级使用及最佳实践&#xff08;续&#xff09;1. 复杂查询与联合查询复杂查询示例 2. 数据同步与一致性示例&#xff1a;使用事务确保数据一致性 3. 数据分页加载示例&#xff1a;分页加载数据 4. 内容提供者…

【CN】Argo 持续集成和交付(二)

7.25.通知 概述 Argo CD 通知持续监控 Argo CD 应用程序&#xff0c;并提供一种灵活的方式来通知用户应用程序状态的重要变化。使用灵活的触发器和模板机制&#xff0c;可以配置何时发送通知以及通知内容。Argo CD 通知包含有用的触发器和模板目录。因此&#xff0c;可以直接…

pycharm连接mysql

1、按照下图在pycharm找到数据库设置 在PyCharm右侧工具栏有Database&#xff0c;点击打开如果没有&#xff0c;则在view | Tool Windows | Database 选择显示 2、按照下图所示位置找到mysql&#xff08;本机由于配置过&#xff0c;所以由recent&#xff0c;第一次配置在列表中…

Cybersecurity ASPICE实施策略-基于ISO/SAE 21434-亚远景科技

近几年&#xff0c;随着软件定义汽车和汽车的智能化和网联化&#xff0c;使得汽车融合了现代通信与网络通信技术&#xff0c;实现了车与人、车与车、车与道路、车与云端等智能信息交互和共享&#xff0c;也让车具备了环境感知、协同控制、智能决策等功能&#xff1b;与此同时&a…

苹果推送iOS 18.1带来Apple Intelligence预览

&#x1f989; AI新闻 &#x1f680; 苹果推送iOS 18.1带来Apple Intelligence预览 摘要&#xff1a;苹果向iPhone和iPad用户推送iOS 18.1和iPadOS 18.1开发者预览版Beta更新&#xff0c;带来“Apple Intelligence”预览。目前仅支持M1芯片或更高版本的设备。Apple Intellige…

使用 Elasticsearch 和 LlamaIndex 保护 RAG 中的敏感信息和 PII 信息

作者&#xff1a;来自 Elastic Srikanth Manvi 在这篇文章中&#xff0c;我们将研究在 RAG&#xff08;检索增强生成&#xff09;流程中使用公共 LLMs 时保护个人身份信息 (personal identifiable information - PII) 和敏感数据的方法。我们将探索使用开源库和正则表达式屏蔽 …

正余弦算法作者又提出新算法!徒步优化算法(HOA)-2024年一区顶刊新算法-公式原理详解与性能测评 Matlab代码免费获取

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 目录 原理简介 算法伪代码 性能测评 参考文献 …

基于vue-onlyoffice实现企业office web在线应用

目录 1.背景... 1 2.Onlyoffice介绍... 2 3.Onlyoffice核心api介绍... 2 3.1 ApiDocument 2 3.2 ApiParagraph. 2 3.3 ApiTable. 2 3.4. ApiRange. 3 4.Onlyoffice插件介绍... 3 4.1 插件定义... 3 4.2 插件对象... 3 4.3 插件结构... 4 4.4 插件内嵌使用方式... 4…

搜索引擎项目(四)

SearchEngine 王宇璇/submit - 码云 - 开源中国 (gitee.com) 基于Servlet完成前后端交互 WebServlet("/searcher") public class DocSearcherServlet extends HttpServlet {private static DocSearcher docSearcher new DocSearcher();private ObjectMapper obje…

Luma AI发布文生视频大模型Dream Machine——可免费在线试玩

Sora模型的文生视频能力&#xff0c;想必一定惊艳过你。虽然Sora模型很惊艳&#xff0c;但是并没有开放给普通大众。Luma AI发布文生视频大模型Dream Machine模型&#xff0c;可以免费供大家使用&#xff0c;任何人只要到Luma AI的官方网站&#xff0c;就可体验Luma AI的文生视…

六个开源的PDF转Markdown项目

✨ 1: gptpdf gptpdf 是一个利用VLLM解析PDF为Markdown的工具&#xff0c;几乎完美支持数学公式、表格等。 GPTPDF 是一个使用视觉大模型&#xff08;如 GPT-4o&#xff09;将 PDF 文件解析成 Markdown 文件的工具。它主要用于高效地解析 PDF 文档中的排版、数学公式、表格、…

React Native新架构系列-新架构介绍

从今天起&#xff0c;会陆续更新React Native新架构相关的系列内容&#xff0c;本系列基于React Native 0.73.4版本&#xff0c;从一名Android开发者的视角进行介绍。本系列介绍的内容默认读者对React Native有一定的了解&#xff0c;对基础的开发内容不再赘述。 前言 首先介绍…

【优选算法】——leetcode——438.找到字符串中所有字母异位词

目录 1.题目 2.题目理解 3.算法原理 1.如何快速判断两个字符串是否是异位词 2.解决问题 暴力求解——>滑动窗口哈希表 滑动窗口 利用滑动窗口哈希表解决问题 优化&#xff1a;更新结果的判断条件 4.编程代码 C代码 1.频率统计 2. 双指针 C语言代码 1.字符频率…

【qt小系统】传感器云平台3D散点图(附源码)

摘要&#xff1a;本文主要使用QT5&#xff0c;实现了一个传感器云平台的小示例&#xff0c;模拟的是各类传感器的添加&#xff0c;例如&#xff1a;热成像传感器、温度传感器、超声波传感器&#xff0c;模拟添加完成后&#xff0c;会自动将此传感器的三维坐标增加到3D散点图上&…

Vmware安装openstack

安装虚拟机 创建完成后&#xff0c;点击开启虚拟机 稍等执行成功后 上传压缩包到指定目录。将yoga_patch.tar.gz包上传至/root目录下&#xff0c;将stack3_without_data.tar.gz包使用WinSCP上传至/opt目录下 vim run_yoga.sh #/bin/bash cd /root sudo apt-get update tar -xzv…

「问题解决」jdk高版本导致请求返回对象转换报错

报错&#xff1a;Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException accessible: module java.base does not “opens java.lang” to unn…