软件教练说:性能优化与性能设计,“相亲相爱”的一对

本文探讨了软件性能优化的重要性,强调了性能优化与性能设计的互补关系。文章分为架构优化、算法优化、代码优化和编译优化等多个方面,详细介绍了负载均衡、多线程协程、哈希表、二分查找、跳表等技术,并提供了实际的优化策略,如延迟计算、预计算、内存和缓存优化。通过实例和常见问题解答,揭示了性能优化的实践方法和思考路径。
摘要由CSDN通过智能技术生成

 摘要: 性能优化通常是在现有系统和代码基础上做改进,考验的是开发者反向修复的能力,而性能设计考验的是设计者的正向设计能力,但性能优化的方法可以指导性能设计,两者互补。

性能优化是指在不影响正确性的前提下,使程序运行得更快,它是一个非常广泛的话题。

优化有时候是为了降低成本,但有时候,性能能决定一个产品的成败,比如游戏服务器的团战玩法需要单服达到一定的同时在线人数才能支撑起这类玩法,而电信软件的性能往往是竞标的核心竞争力,性能关乎商业成败。

软件产品多种多样,影响程序执行效率的因素很多,因此,性能优化,特别是对不熟悉的项目做优化,不是一件容易的事。

性能优化可分为 宏观 和 微观 两个层面。宏观层面包括架构重构,而微观层面,则包括算法的优化,编译优化,工具分析,高性能编码等,这些方法是有可能独立于具体业务逻辑,因而有更加广泛的适应性,且更易于实施。

具体到性能优化的方法论,首先, 应建立度量 ,你度量什么,你得到什么。所以,性能优化测试先行,须基于数据而不能凭空猜测,这是做优化的一个基本原则。搭建真实的压测环境,或者逼近真实环境,有时候是困难的,也可能非常耗费时间,但它依然是值得的。

有许多工具能帮助我们定位程序瓶颈,有些工具能做很友好的图形化展示,定位问题是解决问题的前置条件,但定位问题可能不是最难的,分析和优化才是最耗时的关键环节,修改之后,要再回归测试,验证是否如预期般有效。

什么是高性能程序?架构致广远、实现尽精微。

架构优化的关键是识别瓶颈,这类优化有很多套路: 比如通过负载均衡做分布式改造,比如用多线程协程做并行化改造,比如用消息队列做异步化和解耦,比如用事件通知替代轮询,比如为数据访问增加缓存,比如用批处理+预取提升吞吐,比如IO与逻辑分离、读写分离等等。

架构调整和优化虽然收效很大,却因受限于各种现实因素,因而并不总是可行。

能不做的尽量不做、必须做的高效做是性能优化的一个根本法则, 提升处理能力和降低计算量 可视为性能优化的两个方向。

有时候,我们不得不从细节的维度去改进程序。通常,我们应该使用简单的数据结构和算法,但如有必要,就应积极使用更高效的结构和算法,不止逻辑结构,实现结构(存储)同样影响执行效率;分支预测、反馈优化、启发性以及基于机器学习编译优化的效果日益凸显;熟练掌握编程语言深刻理解标准库实现能帮助我们规避低性能陷阱;深入细节做代码微调甚至指令级优化有时候也能取得意想不到的效果。

有时候,我们需要做一些交换,比如用空间置换时间,比如牺牲一些通用性可读性换取高性能,我们只应当在非常必要的情况下才这么做,它是 权衡的艺术。

1、架构优化

通常系统的throughput越大,latency就越高,但过高的latency不可接受,所以架构优化不是一味追求throughput,也需要关注latency,追求可接受latency下的高throughput。

负载均衡

负载均衡其实就是解决一个分活的问题,对应到分布式系统,一般在逻辑服的前面都会安放一个负载均衡器,比如NGINX就是经典的解决方案。负载均衡不限于分布式系统,对于多线程架构的服务器内部,也需要解决负载均衡的问题,让各个worker线程的负载均衡。

多线程、协程并行化

虽然硬件架构的复杂化对程序开发提出了更高的要求,但编写充分利用多CPU多核特性的程序能获得令人惊叹的收益,所以,在同样硬件规格下,基于多线程/协程的并行化改造依然值得尝试。

多线程不可避免要面临资源竞争的问题,我们的设计目标应该是充分利用硬件多执行核心的优势,减少等待,让多个执行流畅快的奔跑起来。

对于多线程模型,如果把每一个要干的活抽象为一个task,把干活的线程抽象为worker,那么,有两种典型的设计思路,一种是对task类型做出划分,让一类或者一个worker去干特定的task,另一种是让所有worker去干所有task。

第一种划分,能减少数据争用,编码实现也更简单,只需要识别有限的竞争,就能让系统工作的很好,缺点是任务的工作量很可能不同,有可能导致有些worker忙碌而另一些空闲。

第二种划分,优点是能均衡,缺点是编码复杂性高,数据竞争多。

有时候,我们会综合上述两种模式,比如让单独的线程去做IO(收发包)+反序列化(产生protocol task),然后启动一批worker线程去处理包,中间通过一个task queue去连接,这即是经典的生产者消费者模型。

协程是一种用户态的多执行流,它基于一个假设,即用户态的任务切换成本低于系统的线程切换。

通知替代轮询

轮询即不停询问,就像你每隔几分钟去一趟宿管那里查看是否有信件,而通知是你告诉宿管阿姨,你有信的时候,她打电话通知你,显然轮询耗费CPU,而通知机制效率更高。

添加缓存

缓存的理论依据是 局部性原理。

一般系统的写入请求远少于读请求,针对写少读多的场景,很适合引入缓存集群。

在写数据库的时候同时写一份数据到缓存集群里,然后用缓存集群来承载大部分的读请求,因为缓存集群很容易做到高性能,所以,这样的话,通过缓存集群,就可以用更少的机器资源承载更高的并发。

缓存的命中率一般能做到很高,而且速度很快,处理能力也强(单机很容易做到几万并发),是理想的解决方案。

CDN本质上就是缓存,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值