性能优化还不会?吃掉这五个类别,摆平性能优化
4. 延后 / 惰性处理
延后 / 惰性处理策略和前面说的预先 / 提前处理正好相反。就是尽量将操作(比如计算),推迟到必需执行的时刻,这样很可能避免多余的操作,甚至根本不用操作。
运用这一策略最有名的例子,就是 COW(Copy On Write,写时复制)。假设多个线程都想操作一份数据,一般情况下,每个线程可以自己拷贝一份,放到自己的空间里面。但是拷贝的操作很费时间。系统如果采用惰性处理,就会将拷贝的操作推迟。如果多个线程对这份数据只有读的请求,那么同一个数据资源是可以共享的,因为“读”的操作不会改变这份数据。当某个线程需要修改这一数据时(写操作),系统就将资源拷贝一份给该线程使用,允许改写,这样就不会影响别的线程。
COW 最广为人知的应用场景有两个。一个是 Unix 系统 fork 调用产生的子进程共享父进程的地址空间,只有到某个子进程需要进行写操作才会拷贝一份。另一个是高级语言的类和
容器,比如 Java 中的 CopyOnWrite 容器,用于多线程并发情况下的高效访问。C++ 里面经常使用的 STL 标准模板库中的很多类,比如 string 类,也是具有写时才拷贝技术的类。
三、并行 / 异步操作
===========
优化策略的第三大类是“并行 / 异步操作”。并行和异步两种操作虽然看起来很不一样,其实有异曲同工之妙,就是都把一条流水线和处理过程分成了几条,不管是物理上分还是逻辑上分。
5. 并行操作
并行操作是一种物理上把一条流水线分成好几条的策略。直观上说,一个人干不完的活,那就多找几个人来干。并行操作既增加了系统的吞吐量,又减少了用户的平均等待时间。比如现代的 CPU 都有很多核,每个核上都可以独立地运行线程,这就是并行操作。
并行操作需要我们的程序有扩展性,不能扩展的程序,就无法进行并行处理。这里的并行概念有不同的粒度,比如是在服务器的粒度(所谓的横向扩展),还是在多线程的粒度,甚至是在指令级别的粒度。
绝大多数互联网服务器,要么使用多进程,要么使用多线程来处理用户的请求,以充分利用多核 CPU。另外一种情况就是在有 IO 阻塞的地方,也是非常适合使用多线程并行操作的,因为这种情况 CPU 基本上是空闲状态,多线程可以让 CPU 多干点活。
6. 异步操作
异步操作这一策略和并行操作不同,这是一种逻辑上把一条流水线分成几条的策略。
我们首先在编程的领域澄清一下概念:同步和异步。同步和异步的区别在于一个函数调用之后,是否直接返回结果。如果函数挂起,直到获得结果才返回,这是同步;如果函数马上返回,等数据到达再通知函数,那么这就是异步。
我们知道 Unix 下的文件操作,是有 block 和 non-block 的方式的,有些系统调用也是block 式的,如:Socket 下的 select 等。如果我们的程序一直是同步操作,那么就会非常影响性能。采用异步操作的话,虽然稍微增加一点程序的复杂度,但会让性能的吞吐率有很大提升。
现代的语言往往对异步操作有比较好的支持,使得异步编程变得更加简单,可读性也更好。
四、缓存 / 批量合并
===========
“缓存 / 批量合并”是优化策略中的第四大类。缓存和批量合并这两个策略,有些场景下会同时起作用,所以我把它们放在一起。
7. 缓存数据
缓存的本质是加速访问。这是一个用得非常普遍的策略,几乎体现在计算机系统里面每一个模块和领域,CPU、内存、文件系统、存储系统、内容分布、数据库等等,都会遵循这样的策略。
我们最熟悉的应该就是 CPU 的各级缓存了。在文件系统、存储系统和数据库系统里面,也有快速缓存来存储经常访问的数据,目的是尽量提高缓存命中率,从而避免访问比较慢的存储介质。
对于一个基于 Web 的应用服务,前端会有浏览器缓存,有 CDN 存放在边缘服务器上,有反向代理提供的静态内容缓存;后端则还会有服务器本地缓存。
程序设计中,对于可能重复创建和销毁,且创建销毁代价很大的对象(比如套接字和线程),也可以缓存,对应的缓存形式,就是连接池和线程池等。
对于消耗较大的计算,也可以将计算结果缓存起来,下次可以直接读取结果。比如对递归代码的一个有效优化手段,就是缓存中间结果。
8. 批量合并处理
在有 IO(比如网络 IO 和磁盘 IO)的时候,合并操作和批量操作往往能提升吞吐量,提高性能。
我们最常见的是批量 IO 读写。就是在有多次 IO 的时候,可以把它们合并成一次读写数据。这样可以减少读写时间和协议负担。比如,GFS 写文件的时候,尽量批量写,以减少IO 开销。
对数据库的读写操作,也可以尽量合并。比如,对键值数据库的查询,最好一次查询多个键,而不要分成多次。
涉及到网络请求的时候,网络传输的时间可能远大于请求的处理时间,因此合并网络请求也很有必要。上层协议呢,端到端对话次数尽量不要太频繁(Chatty),否则的话,总的应用层吞吐量不会很高。
五、更先进算法和数据结构
============
优化策略中的最后一个大类就是“更先进算法和数据结构”。这两个策略是紧密配合的,比如先进的算法有时候会需要先进的数据结构;而且它们往往和程序的设计代码直接相关,所以放在一起。
9. 先进的算法
同一个问题,肯定会有不同的算法实现,进而就会有不同的性能。比如各种排序算法,就是各 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 有千秋。有的实现可能是时间换空间,有的实现可能是空间换时间,那么就需要根据你自己的实际情况做权衡。
对每一种具体的场景(包括输入集合大小、时间空间的要求、数据的大小分布等),总会有一种算法是最适合的。我们需要考虑实际情况,来选择这一最优的算法。
10. 高效的数据结构
和算法的情况类似,不同的数据结构的特性,也是千差万别。
没有一个数据结构是在所有情况下都是最好的,比如你可能经常用到的 Java 里面列表的各种实现,包括各种口味的 List、Vector、LinkedList,它们孰优孰劣,取决于很多个指标:添加元素、删除元素、查询元素、遍历耗时等等。我们同样要权衡取舍,找出实际场合下最适合的高效的数据结构。
六、总结
====
各种性能问题的解决,需要采用一些策略;而且不同的人和不同的场景中,会采用有时相同有时迥异的策略,恰如韩愈所说的“草树知春不久归,百般红紫斗芳菲”。但花草树木争奇斗艳,说到底是因为“知春不久归”。
同样的道理,这些性能优化策略,有时候很容易想到,有时候并不是那么直观。所以,我们需要系统地有层次地思考,而这一讲就是帮助你建立这样的思路。
通过总结十大策略,希望你可以多从不同角度,思考同一个问题;有时候一个问题看似无解,但多方位思考,可能会突然发现非常好的解决方案。
写在最后
这里给大家分享一个最近我对"性能优化"的一个总结(如下图),因为还有一些比较细的知识点还没整理好,故这次就只给大家分享一个比较广的一个"性能优化总结图"
性能优化还不会?吃掉这五个类别,摆平性能优化相关推荐
- 性能优化还不会?吃掉这五个类别,摆平性能优化~
在针对实际的性能问题的时候,用什么样的解决方案才可以提升性能呢?这就需要你了解具体的优化策略了. 现实中的性能问题和具体领域千差万别,我也不可能面面俱到.但是为了帮助你理解,我总结了十大常用的优化策略 ...
- 第五人格服务器维修要多久才能好,《第五人格》得到官方优化的四个方面,玩家的误触几率有所降低?...
<第五人格>闪退问题终于修复好了吗?四个得到官方优化的方面!<第五人格>得到官方优化的四个方面,玩家的误触几率有所降低?非对称性对抗竞技手游<第五人格>官方每周都会 ...
- 如何优化WebAPP性能:从五个层面上彻底优化前端项目性能
如何优化WebAPP性能:从五个层面上彻底优化前端项目性能 资源层面上的优化 该项措施可以帮助我们优化 FP.FCP.LCP 指标. 压缩文件.使用 Tree-shaking 删除无用代码 服务端配置 ...
- 原来前端性能优化还可以这么玩?
事件委托 事件委托(也叫事件代理)利用了事件冒泡,把监听函数绑定在父容器上.在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息. 使用事件委托的优点: a. ...
- lua jit java jit_Lua JIT 2.0 发布了,一百五十倍的性能提升!
jzhang 2014-4-7 15:44:00 阅读(2432) 评论(2) 先把官方主页摆出来: 外链网址已屏蔽luajit.org/luajit.html Lua JIT 1.0早就有了,但是性 ...
- 并行算法设计与性能优化 刘文志 第4章 串行代码性能优化
一方面,串行代码优化有时能获得成千上万倍的加速:另一方面因为单个并行控制流的内部依旧是串行的. 一般而言,不同算法上的优化是最有效的.假设你已经有了一个能得到正确结果的程序,需要在此基础上进行优化,本 ...
- 《Java性能调优实战》笔记(一)Java编程性能调优、多线程性能优化
文章目录 一.Java性能调优概述 1.1 性能调优标准 1.2 制定性能调优策略 二.Java编程性能调优 2.1 字符串 2.2 正则表达式 2.3 ArrayList和LinkedList的选择 ...
- Linux五种IO模型性能分析
转载:http://blog.csdn.net/jay900323/article/details/18141217 Linux五种IO模型性能分析 目录(?)[-] 概念理解 Linux下的 ...
- GPU 编程入门到精通(五)之 GPU 程序优化进阶
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 博主由于工作当中的需要,开始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GP ...
最新文章
- 【NOIP2016】愤怒的小鸟
- HDU 4609 3idiots
- java session使用_使用Neo4j和Java进行大数据分析 第2部分
- 用Java访问带有Kerberos认证的HBase
- python解图片迷宫生成路径_用Python代码来解图片迷宫的方法整理
- vue,watch监听数据,数据监听
- python为list实现find方法
- sentinel 打包_SpringCloud Alibaba整合Sentinel
- 深度学习head、neck、backbone三个术语分别是指什么?
- 记录一个SetupFactory使用手册
- 中国微型连接器市场趋势报告、技术动态创新及市场预测
- HTML网页标签代码基本教学(1)基本标签学习
- 【51单片机】74HC595串转并 使用
- java垃圾回收策论,share_doucument/jvm的垃圾回收策略.md at develop · LiuLei0571/share_doucument · GitHub...
- AirDisk存宝 【S3\S6简易使用说明】
- 批处理命令html文件合并,cmd命令行无损合并批处理TS视频文件
- tibco文档下载地址
- 学习VM上运行dnf(整理)
- 基于STM32单片机的差分升级(增量升级)算法
- 读和写,关于cache和buffer