常见的性能优化思维 我会带着你远行 2021-09-21 23:54 289阅读 0赞 ### 1、【练技术】如何通过精研线程模型,cpu调度,内存模型等性能优化核心? ### 性能优化无非就是线程,cpu调度,以及内存之间的配合,这三者中任何一个达到极限,都会造成系统整体性能下降,甚至瘫痪。 线程必然要由cpu调度才能活动起来,那么线程的活动也必须有自己的地盘,那么这个地盘就是内存区域。线程数越多,需要cpu的调度能力越强,需要的内存也就越大,那么线程不可能无限增大,总有个极限,当到达极限之后,系统性能将呈现抛物线形的状态急转往下。 所以我们必须不能让cpu等资源达到这个极限值,一般在85%左右就可以了。intel的工程师曾今说过,我们为什么要让cpu达到100%的性能呢,能够让他发挥到80%-85%就已经很完美了。 那么线程模型也是掣肘性能的一个重要因素,NIO优于BIO,reactor模型又是NIO模型的最佳实践,proactor模型又优于reactor模型。这些线程模型都是值得我们去深入研究的。 每种线程模型都有实际的产品落地,比如早期的tomcat就是BIO模型的,后来NIO起来之后,netty,redis等都基于reactor实现了相对不错的性能。proactor模式又落地到tomcat的NIO2通道中。这些都是优秀的线程模型的实现案例。 java领域里面,内存模型的研究的终极目标是如何更有效率的回收垃圾,从jdk迭代的版本我们可以看出jvm工程师在这方面的努力,在【jvm调优-GC篇】里我们着重讲了各种垃圾收集算法以及产品的落地,从最初的串行垃圾收集器到当前性能最好的G1垃圾收集器,这些都凝聚jvm工程师的心血。 在内存领域,各路大牛可谓都是绞尽脑汁的琢磨各种方案,也取得了一些成效,比如“零拷贝”,这个技术用在各大组件中,nginx,netty,kafka等组件里都有他的影子。他的理念就是干脆跨过堆内存,直接走内核,这样就没gc啥事了。 所以我们调优要做到心中有数,你究竟要调什么?究竟是线程模型呢,还是cpu调度呢,还是内存gc回收呢?针对不同的部分都有成熟的方案可选,不要盲目的去调优。 ### 2、【学心法】如何从源码角度体会作者的设计思想? ### 我们在做项目时候一般会遇到下面的问题: * **问题一**是不知道如何去设计,比如刚入职场时,来一个需求需做概要设计,不知如何下手,不得不去看当前系统类似需求是如何设计的,然后仿照去设计。 * **问题二**是设计的时候,考虑问题不周全,相比职场新手,这类人对一个需求依靠自己的经验已经能够拿出一个概要设计,但是设计中经常会遗漏一些异常细节,比如使用多线程有界队列执行任务,遇到机器宕机了,如果队列里面的任务不存盘的话,那么机器下次启动时候这些任务就丢失了。 对于这些问题,说到底主要是因为经验不够,而经验主要从项目实践中积累,所以招聘单位一般都会限定工作时间大于 3 年,因为这些人的项目经验相对较丰富,项目中遇到的场景相对较多。工作经验的积累来自于年限与实践,然而看源码可以扩展我们的思路,这是变相增加我们经验的不错方法。虽然不能短时间内通过时间积累经验,但是可以通过学习开源框架、开源项目来获取。 * 另外进职场后一般都要先熟悉现有系统,如果有文档还好,没文档的话就得自己去翻代码研究。如果大家之前对阅读源码有经验,那么在研究新系统的代码逻辑时就不会那么费劲了。 * 还有一点就是当你使用框架或者工具做开发时,如果你对它的实现有所了解,就能最大化的减少出故障的可能。比如并发队列 ArrayBlockingQueue 里面元素入队有个 offer 和 put 方法,虽然某个时间点你知道使用 offer 方法时,当队列满了就会丢弃要入队的元素,之后 offer 方法会返回 false,而不会阻塞当前线程;使用 put 方法时当队列满了,则会挂起当前线程,直到队列有空闲元素,入队成功后才返回。但是人是善忘的,当你一段时间不使用,就会忘记他们的区别,这时当你使用时,需进入 offer 和 put 的源码看他们的实现。进入 offer 方法一看,哦,原来队列满后直接返回了 false;进入 put 方法一看,哦,原来队列满后,直接使用条件变量的 await 方法挂起了当前线程;知道了他们的区别,你就可以根据自己的需求来选择了。 看源码最大的好处是可以开阔思维,提升架构设计能力。有些东西仅靠书本和自己思考是很难学到的,必须通过看源码,看别人如何设计,然后思考为何这样设计才能获取。能力的提高不在于你写了多少代码,做了多少项目,而在于给你一个业务场景时,你是否能拿出几种靠谱的解决方案,并且说出各自的优缺点。而如何才能拿出来,一来靠经验,二来靠归纳总结,而看源码可以快速增加你的经验。 ### 3、【炼内功】如何在系统设计初期就能预测未来的性能状况? ### 在做系统架构设计的时候,我们对现有的资源,包括软硬件资源都应该有个清晰的了解。比如说现在公司机房里预备给我们系统上线的物理机的cpu是几核的,内存是多大的,硬盘是不是ssd的,带宽是多少,等等。这些信息都是我们设计人员必须要了解的,尤其是作为架构师,更要做到心中有数,这对你做架构设计的时候非常有参考意义。 举个简单的例子,你可能在一台2核4g的物理机上架构nginx+tomcat+redis吗?你把这3个组件都放在一台只有4G内存的机器上你认为能行吗? 答案肯定是不行的,光跑一个tomcat都费劲,对不对?所以硬件性能决定了你能用哪些组件,对于一些比较重的组件尽量少用,比如08,09年甚至更早的时候我们用的比较多的weblogic和websphere等等。光启动起来啥事不干就吃掉几个G的内存,如果再在上面跑业务那你的机器起码得配置到32g内存,所以这种重量级的组件也渐渐被我们淘汰了。所以针对不同的软硬件的组合我们该如何在软硬件性能受限的情况下设计出最合适的框架,这是个值得深思的问题。 当你根据现实情况设计出来框架后你也必然知道这个框架究竟能承受多少并发,这都是一目了然的。 ### 4、【悟思维】项目架构决定性能?优秀的架构胜过一万次的调优 ### 这个问题很容易理解,一个单节点(一台应用服务器+一台数据库服务器)的系统架构,任凭你使出浑身解数来调优也不可能让系统达到百万级并发,别说百万级了,上万并发都不可能。不说其他的,在一个性能相对不错的物理机上,mysql最多也就能承载3500-4500的QPS,你说你能调优调到上万并发??在目前来看如果不借助于其他组件或者其他技术手段是不太可能的。 首先大家要明白一个最底层的逻辑,所有的性能问题归根结底绝大多数都是要解决IO的读写性能问题。 我们在线程模型上面孜孜不倦的追求,从BIO到NIO,再到reactor,最后到proactor,对这些模型的追求本质上就是不断对IO性能的追求。 那IO又分为读IO和写IO,在单节点上,高并发上来之后,请求直接通过tomcat打到mysql上达到3500qps左右的时候,mysql就会报警了,这时候怎么办? 打到mysql上的请求无非就是读和写,所以我们分两种情况来处理: * 一是解决读IO的问题,如何解决?最直接的就是我们把热点数据直接放内存里(走逻辑io),不走mysql了(走mysql实际是到磁盘去拿数据的,走的是物理IO),所以我们大名鼎鼎的redis就派上用场了。绝大部分热点数据都存放在redis,高并发时候,读IO绝大部分都走redis了,这样就减轻了mysql的负担。 * 二是解决写IO的问题,当大量的写需求到达mysql的时候,如果我们在mysql前面加上消息队列相关组件,让写请求先进队列,然后再通过队列慢慢依次的来对mysql进行写操作,那么这样不就减轻了mysql的写请求IO了吗? 所以我们的架构就从单一架构(比如说是tomcat+mysql)变成了(tomcat+mq+redis+mysql)的架构,这两种架构的性能有着天壤之别。因为mq和redis分别解决了高并发时的读写问题,这才是影响性能的根本因素。那么第二种架构还有很多的优化空间,比如我们继续给他增加多级缓存,redis再做集群,mq也做集群,甚至tomcat,mysql都做集群,那么这个系统将会变的非常庞大,也更加的复杂,但是带来的效果却是显而易见的,达到百万并发,千万并发甚至亿级并发都是有可能的。 ### 5、【升境界】预防大于一切,不要等待项目灾难来临才想起去优化。 ### 我们系统为什么都要配有监控系统,尤其是针对高并发的主营系统,监控系统是必备的。因为不管从技术层面还是从业务层面讲,主营系统的奔溃都会给公司带来不可估量的损失。 项目灾难让公司损失百万,千万的案例实在是多不胜数。所以预防大于一切这个说法一点也不为过。通常我们在监控系统上面设置的阈值都会比最大极限值要低5-10个百分点,如果最大极限值是85%,那我们设置告警值一般是75%就会告警,不会真的让你达到85%才告警,有些谨慎的公司这个值设置的更低。 这样会让运维人员和开发人员及时介入进行排查,不会让系统奔溃了再来排查,到那时候就晚了。所以如果一个功能经常性的达到阈值的75%从而触发报警,这时候开发人员就应该立即去排查这个故障,通过不断的修改和调优,这个功能逐渐的完善,报警也没有了。 所以这才是一个系统调优的正确姿势,绝对不能等到系统奔溃才去优化,我们要做的是尽可能的做到各个层面的预防,运维,开发,DBA等各司其职,保证系统7\*24小时稳定运转。 ### 6、【拓格局】反对没有经过验证人云亦云的性能调优经验。 ### 做学问最忌讳人云亦云,尤其是在技术领域,没有经过验证的所谓经验最好不要一味的去相信,更不要在线上尝试一些根本没有依据的所谓调优经验,因为你有可能把一个正常的系统调奔溃。 比如tomcat某个参数的设置,其实是和版本相关的,你好像听别人说过可以调整这个参数,这时候你不管三七二十一拿过来就改,最后肯定不能达到自己的预期,还有可能把原来运转正常的系统搞奔溃。 像tomcat通道的配置都是根据版本的不同有不同的配置,比如你就不能在tomcat7上配置NIO2通道,因为NIO2虽然性能高,但是必须是tomcat8及以上版本才可以配置。如果你只是听别人这么说过NIO2通道性能高,自己从来没有尝试调试过,也没有尝试去配置过,然后就想当然的在tomcat7上面配置NIO2通道,最后必定会捅娄子,出纰漏。 所以对于调优经验还是要实事求是,经过研究的才有发言权,只有经过实践的你才敢去调,这样自己也不会心虚。
相关 性能优化:Java代码中常见的性能瓶颈案例 在Java代码中,常见的性能瓶颈可以归结为以下几个方面: 1. **数组/列表操作**: - 大量的创建、删除或遍历操作会导致性能问题。 - 建议使用高效的数据结 - 日理万妓/ 2024年10月23日 11:09/ 0 赞/ 35 阅读
相关 关于Java性能优化的常见误区 在Java性能优化过程中,可能会出现一些常见的误区。以下是其中的一些: 1. **CPU利用率是全部**:Java应用通常会使用操作系统资源,如CPU和内存。但认为Java应 港控/mmm°/ 2024年10月07日 00:12/ 0 赞/ 47 阅读
相关 性能优化:Java代码中常见的性能瓶颈 在Java编程中,常见的性能瓶颈主要集中在以下几个方面: 1. **循环效率**:过多的循环和迭代会导致性能下降。尽量减少循环次数,并利用多线程提高并发执行能力。 2. * 谁践踏了优雅/ 2024年09月11日 05:00/ 0 赞/ 77 阅读
相关 【数据库优化】后端思维之数据库性能优化方案 前言 毫不夸张的说咱们后端工程师,无论在哪家公司,呆在哪个团队,做哪个系统,遇到的第一个让人头疼的问题绝对是数据库性能问题。如果我们有一套成熟的方法论,能让大家快速、 ╰半橙微兮°/ 2024年04月01日 09:37/ 0 赞/ 81 阅读
相关 vue中常见的性能优化 一、编码优化: 1.不要将所有的数据都放在data中,data中的数据都会增加getter和setter,会收集对应的 watcher,这样就会降低性能。 2. vue 红太狼/ 2022年12月27日 04:51/ 0 赞/ 180 阅读
相关 前端开发中常见的性能优化 1、 减少http请求次数:css spirit,data uri 2、JS,CSS源码压缩 3、 前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,前端 今天药忘吃喽~/ 2022年07月14日 14:18/ 0 赞/ 185 阅读
相关 常见性能优化策略的总结 原文地址:[http://tech.meituan.com/performance\_tunning.html][http_tech.meituan.com_performa 红太狼/ 2022年07月12日 02:04/ 0 赞/ 208 阅读
相关 WEB前端性能优化常见方法 web前端是应用服务器处理之前的部分,前端主要包括:HTML,CSS,javascript,image等各种资源,针对不同的资源有不同的优化方式。 内容优化 超、凢脫俗/ 2022年04月04日 10:53/ 0 赞/ 189 阅读
相关 常见的性能优化思维 1、【练技术】如何通过精研线程模型,cpu调度,内存模型等性能优化核心? 性能优化无非就是线程,cpu调度,以及内存之间的配合,这三者中任何一个达到极限,都会造成系统整体 我会带着你远行/ 2021年09月21日 23:54/ 0 赞/ 290 阅读
还没有评论,来说两句吧...