性能优化:空间换时间
问题背景
校验分为两种:简单校验和复杂校验。
对于一些简单的校验,如用户是否存在,密码是否正确等等。这种校验,可以说几乎不耗时的。所以也没必要在这里做优化。
对于复杂的校验,需要进行联合查询,通过查询很多次之后,才可以得出 数据的正确性与否。当然这种校验执行会很慢。
对于程序开发来说,时间复杂度和空间复杂度是可以相互转化的。说通俗一点,就是:对于执行的慢的程序,可以通过消耗内存(即构造新的数据结构)来进行优化。而消耗内存的程序,也可以多消耗时间来降低内存的消耗。
前者使用的是最多的。很少有人会为了节省内存而浪费时间。
感兴趣的同学,请仔细看完这个例子。看如何是如何消耗内存来提高性能的。如果有不正确的地方,还请指出来。
比如说给学生 排课。 学生 和 课程 是一个多对多的关系。
处理方式对比
方案一:正常的处理方式:
当一个学生进行再次选课的时候。需要查询学生选课表看是否已经存在。
即有如下校验:
//查询 学生code和课程code分别为 A 和 B的数据是否存在//list集合中存放 学生选课记录全部的数据
List<StudentRecordEntity> ListStudentRecord=service.findAll();
//查询数据,看是否已经存在
StudentRecordEntity enSr=ListStudentRecord.find(s=>s.学生Code==A && s.课程Code==B);
If(enSr==null){//学生没有选该课程//....
}else{//学生已经选过该课程//....
}
对于上面这种代码的写法,非常的简练。而且也非常易懂。
首先,假设有5000个学生,100门课程。那么对于学生选课的数据集中,数据量将是5000*100.数据量会是十万级别的数量级。
在十万条数据中,查询 学生=A 课程=B的 一条记录。执行的效率会很低。因为find方法的查询也就是where 查询,即通过遍历数据集合 来查找。
所以,使用上面的代码。在数据量逐渐增长的过程中,程序的执行效率会大幅度下降。
(ps:数据量增长,在该例子中并不太适合。例子可能不太恰当。总之,大概就是这个意思。)
方案二:使用内存进行优化效率:
这种做法,需要消耗内存。或者说把校验的工作向前做(数据的初始化,在部署系统的过程中进行)。即:在页面加载的时候数据只调用提供的public方法进行校验。
//学生Code 到 数组索引
Private Dictionary<string,int> _DicStudentCodeToArrayIndex;
//课程Code 到 数据索引
Private Dictionary<string,int> _DicCourseCodeToArrayIndex;//所有学生
List<StudentEntity> ListStudent=service.findAllStudent();
//所有课程
List<CourseEntity> ListCourse=service.findAllCourse();
//所有 学生选课记录
List<StudentCourseEntity> ListStudentRecord=service.finAll();Private int[,] _ConnStudentRecord=new int[ListStudent.count,ListCourse.count];//构造 学生、课程的 数组 用于快速查找字典索引
Private void GenerateDic(){For(int i=0;i<ListStudent.Count;i++)_DicStudentCodeToArrayIndex.Add(ListStudent[i].code,i)}For(int i=0;i<ListCourse.Count;i++){_DicCourseCodeToArrayIndex.Add(ListCourse[i].code,i)}
}//构造学生选课 匹配的 二维数组。 1表示 学生已选该课程
Private void GenerateArray(){Foreach(StudentRecordEntity sre in ListStudentRecord){Int x=_DicStudentCodeToArrayIndex[sre.学生Code];Int y=DicCourseCodeToArrayIndex[sre.课程Code];ConnStudentRecord[x,y]=1;}
}//对外公开的方法:根据学生Code 和课程Code 查询 选课记录是否存在
/// <returns>返回1 表示存在。返回0表示不存在</returns>
Public void VerifyRecordByStudentCodeAndCourseCode(String pStudentCode,String pCourseCode){Int x=_DicStudentCodeToArrayIndex[pStudentCode];Int y=_DicCourseCodeToArrayIndex[pCourseCode];Return ConnStudentRecord[x,y];
}
性能分析
分析一下第二种方案的表象。
1、方法很多。
2、使用的变量很多。
首先要说一下。该优化的目的,是提高 学生在选课的时候,所出现的卡顿现象(校验数据量大)。
分别对以上两种方案进行分析:
假设学生为N,课程为M
第一种方案:
时间复杂度很容易计算 第一种方案最小为O(NM)
1、代码多。但是给用户提供的只有一个VerifyRecordByStudentCodeAndCourseCode方法。
2、变量多,因为该方案就是要使用内存提高效率的。
这个方法执行流程:1、在Dictionary中使用Code找Index 2、使用Index查询数组。
第一步中,Dictionary中查询是使用的Hash查找算法。时间复杂度为O(lgN) 时间比较快。第二步,时间复杂度为O(1),因为数组 是连续的 使用索引 会直接查找对应的地址。
所以,使用第二种方案进行校验,第二种方案时间复杂度为O(lgN+lgM)
小结
通过上面的分析,可以看出,内存的付出是可以提高程序的执行效率的。以上只是一个例子,优化的好坏取决于使用的数据结构。
性能优化:空间换时间相关推荐
- 前端遍历导致查询数据时间过长_OLAP 服务器,空间换时间可行吗?
[摘要] 全量预汇总真的是提高 OLAP 性能的可行方案吗?点击了解OLAP 服务器,空间换时间可行吗? 多维分析提供拖拽.旋转.切片.钻取等等人机交互操作,必须有秒级的响应速度.而这些操作对应的明细 ...
- ie浏览器查看vue中js_浅析 Vue.js 中那些空间换时间的操作
Hello,各位小伙伴,接下来的一段时间里,我会把我的课程<Vue.js 3.0 核心源码解析>中问题的答案陆续在我的公众号发布,由于课程的问题大多数都是开放性的问题,所以我的答案也不一定 ...
- 什么叫用空间换时间,用时间换空间
什么叫做用空间换时间 用空间换时间是指为了提高程序或算法的效率,将计算机程序中的时间复杂度转化为空间复杂度,即通过使用更多的空间来减少程序运行所需的时间.这种技术在某些情况下可以大幅缩短程序的执行时间 ...
- FPGA之道(62)时空变换之空间换时间
文章目录 前言 时空变换之空间换时间 缓存提速使用 模块复制 同频模块复制 缓存降频复制 缓存降频使用 逻辑拆分 流水线 流水线的由来 如何在组合逻辑中使用流水线 如何在时序逻辑中使用流水线 顺序系统 ...
- 以空间换时间——动态规划算法及其应用:矩阵链相乘
动态规划算法是5大算法基础中最重要的一个,它专门用来解决平面世界下的应用,即会多次使用二维数组. 当然动态规划算法是空间换时间的算法,也就是说:我们可以利用空间资源来使某算法问题的时间复杂度降到最低. ...
- leetcode-383-Ransom Note(以空间换时间)
题目描述: Given an arbitrary ransom note string and another string containing letters from all the magaz ...
- 空间换时间,查表法的经典例子
前言 上一篇分享了:C语言精华知识:表驱动法编程实践 这一篇再分享一个查表法经典的例子. 我们怎么衡量一个函数/代码块/算法的优劣呢?这需要从多个角度看待.本篇笔记我们先不考虑代码可读性.规范性.可移 ...
- [hashmap|空间换时间] leetcode 1 两数之和
[hashmap|空间换时间] leetcode 1 两数之和 1.题目 题目链接 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下 ...
- 空间换时间--程序策略
这几天修改一个去年做的程序,因为程序使用了xml保存的一些数据,整个xml文件结构欠佳,所以每次都需要对数据进行读取运算重新组合才能使用. 朋友需要这个程序多加点功能,于是顺便把这个去年做的不太好的地 ...
- 空间换时间--编程小绝招解决电话区号识别算法问题
空间换时间问题通常都是一个不大的问题里的一个不小的解决方案.首先要理解代码中函数的一个大致的代价,在输入比较固定,计算输出又比较费劲的时候,常常就是空间换时间发挥作用的时候了.通过几个简单的例子您就会 ...
最新文章
- python在化学方面的应用-学材料、化学的要不要担心人工智能抢了自己的饭碗?...
- fiddler 看懂瀑布图Timeline
- 记一种验证日期格式的正则表达式
- 简单的计算机试题,这么简单的MS Office试题基础,一般人都不好意思看!
- 全球及中国玩具收纳箱行业运营模式分析及产销需求预测报告2021年版
- 一文看懂Python(八)-----内置高阶函数用法总结
- SpringSecurity OAuth2四种模式说明
- 今天梦幻诛仙服务器维护多久,《梦幻诛仙》6月10日体验服务器维护公告
- Java生鲜电商平台-团购模块设计与架构
- java eclipse中修改Web项目的URL访问路径
- 爬取嘉兴市人才网即时招聘信息并写入文本TXT完整案例
- C++解析char *p与char p[]
- BZOJ 2429: [HAOI2006]聪明的猴子
- CuInS2/ZnS-PEG量子点|量子点PEG-ZnS/CdSe|PEG修饰的近红外二区量子点ZnO量子点
- C语言中的a = b = c ? d : e;
- 家有妙招:教你一个在淘宝买东西打折的好方法
- 如何在前台输出代码<xmp>,标签,并且是内容自动换行
- 地铁和轻轨交通的特点
- gpib通信协议_【成功案例】生命科学仪器测试设备公司借助凌华GPIB通信卡 突破旧式仪器与系统兼容整合管理的困境...
- 安卓 broadcast简介理解