Java性能优化学习1:理论基础学习与分析

简介: 性能:使用有限的资源在有限的时间内完成工作。最主要的衡量因素就是时间,所以很多衡量指标,都可以把时间作为横轴。

性能是什么


性能:使用有限的资源在有限的时间内完成工作。

最主要的衡量因素就是时间,所以很多衡量指标,都可以把时间作为横轴。


加载缓慢的网站,会受到搜索排名算法的惩罚,从而导致网站排名下降。 因此加载的快慢是性能优化是否合理的一个非常直观的判断因素,但性能指标不仅仅包括单次请求的速度,它还包含更多因素。


性能衡量指标


1、性能指标:吞吐量QPS/TPS/HPS、响应速度

2、响应时间:平均响应时间AVG、百分位数

3、并发量

4、秒开率

5、正确性


吞吐量与响应速度


现在市面上大多数都是分布式的高并发应用,而现在最常用的衡量指标就是吞吐量和响应速度。


如何理解吞吐量和响应速度呢。

可以以路口的红绿灯为例子来模拟,当交通繁忙的时候,如果红绿灯放行时间很长,那么一定会有某一条路口排很长的队,这个时候对于某一辆在排队的车来说,从他等待排队到经过这个红绿灯路口的时间,就是响应时间。

那么吞吐量可以理解为和响应速度有个相对的概念,如果红绿灯时间我们让他变短,那么这个时候每个路口对于某些车辆来说,响应时间可能会变短,但是这个时候频繁的切换红绿灯,就会导致单位时间通过的车辆减少,所以可以认为吞吐量减少了。

这里给定几个确定的开发常用词:


QPS 代表每秒查询的数量,

TPS 代表每秒事务的数量,

HPS 代表每秒的 HTTP 请求数量等,

这都是常用的与吞吐量相关的量化指标。


需要注意的是:在性能优化的时候,我们要搞清楚优化的目标,到底是吞吐量还是响应速度。


有些时候,虽然响应速度比较慢,但整个吞吐量却非常高,比如一些数据库的批量操作、一些缓冲区的合并等。虽然信息的延迟增加了,但如果我们的目标就是吞吐量,那么这显然也可以算是比较大的性能提升。


一般认为:

响应速度是串行执行的优化,通过优化执行步骤解决问题;

吞吐量是并行执行的优化,通过合理利用计算资源达到目标。

一般对于普通的业务来说,优化主要侧重于响应速度,如果响应速度提升了,吞吐量也就提升了。


而现在的环境是追求高并发、高可用、能够抵御住双十一特别大人流的场景、甚至可能还会夹带有云原生的概念,而这些业务场景,两者是都需要的。


响应时间衡量


如何计算响应时间呢?


平均响应时间

也就是常说的指标AVG,能够体现某个业务的平均处理能力。全部加起来除以总数即可。

但是这么算也有弊端,那就是如果有长尾请求的话,长尾请求的影响会被很快平均,导致很多用户的请求变慢,这不能体现在平均耗时指标中。(什么是长尾请求:明显高于均值的那部分占比比较小的请求,业界关于延迟有一个P99的标准,也就是说99%的请求延迟要满足在一定耗时内,剩下的1%会大于这个耗时,而这个1%就会认为是长尾请求。)

既然这里提到了长尾请求,那就顺带讲解一下长尾导致的危害、造成的原因、解决方案。

长尾危害:假设,一个接口提供服务B,有1%的可能性响应时间大于1s,如果此刻一个上游服务A需要完成一次查询,需要同时查询100次的话,那么服务A响应时间超过1s的概率是63%。


0.99的概率是小于1s,100次的概率是0.99^100 = 0.37,小于1s响应的时间是37%的概率。


那么请求大于1s的概率就是63%。


即使服务处理时间超过1秒的比例仅为 0.01% ,当需要同时查询的实例数(Numbers of Servers)达到2000时,服务延时大于1秒的请求数将超过18%。


造成长尾的原因:

共享资源竞争, 周期性的垃圾回收, 运维活动(比如日志备份), 硬件或者软件故障,网络的抖动,都有可能造成。

解决长尾的方法:

微博motan有一种双发机制,它可以有效解决长尾问题,同时能提升系统吞吐量。

传统解决接口超时问题可能通过重试,在一次请求发送之后等待指定的超时时间,如果没有返回则再请求一次,最差情况下要消耗 2 倍的超时时间。


而双发机制则不然,在发送一次请求后等待 P90(在 T1 时间内有 90% 的请求都能返回则称 P90=T1,通常系统的 P90 和程序设置的超时时间相比小很多)时间。


如果请求没有返回则在此刻再次发送一次请求,在超时时间内,这两个请求中取最快返回的那个。


当然,这里有个防雪崩机制,假如,超过一定数量的请求(比如 15%)都在进行双发,则认为服务整体有问题,会自动停止双发。实践证明,双发机制的去长尾效果非常明显


话说回来,为了解决平均响应时间的缺点,同时还要衡量响应时间,我们引入了百分位数概念。


百分位数

这个也比较好理解。圈定一个时间范围,把每次请求的耗时加入一个列表中,然后按照从小到大的顺序将这些时间进行排序。这样,我们取出特定百分位的耗时,这个数字就是 TP 值。可以看到,TP 值(Top Percentile)和中位数、平均数等是类似的,都是一个统计学里的术语。

它的意义是,超过 N% 的请求都在 X 时间内返回。比如 TP90 = 50ms,意思是超过 90th 的请求,都在 50ms 内返回。


这个指标也是非常重要的,它能够反映出应用接口的整体响应情况。比如,某段时间若发生了长时间的 GC,那它的某个时间段之上的指标就会产生严重的抖动,但一些低百分位的数值却很少有变化。


我们一般分为 TP50、TP90、TP95、TP99、TP99.9 等多个段,对高百分位的值要求越高,对系统响应能力的稳定性要求越高。


在这些高稳定性系统中,目标就是要干掉严重影响系统的长尾请求。这部分接口性能数据的收集,会采用更加详细的日志记录方式,而不仅仅靠指标。比如,将某个接口,耗时超过 1s 的入参及执行步骤,详细地输出在日志系统中。


并发量

并发量是指系统同时能处理的请求数量,这个指标反映了系统的负载能力。


在高并发应用中,仅仅高吞吐是不够的,它还必须同时能为多个用户提供服务。并发高时,会导致很严重的共享资源争用问题,我们需要减少资源冲突,以及长时间占用资源的行为。


针对响应时间进行设计,一般来说是万能的。因为响应时间减少,同一时间能够处理的请求必然会增加。值得注意的是,即使是一个秒杀系统,经过层层过滤处理,最终到达某个节点的并发数,大概也就五六十左右。我们在平常的设计中,除非并发量特别低,否则都不需要太过度关注这个指标。


秒开率

现在的用户,如果上网,试想一下,打开一个页面如果要5-6秒那这个网页或者说APP估计评分肯定非常低,秒开是一种特别需要重视的用户体验。


正确性

在进行测试的时候,发现接口响应非常流畅,把并发数增加到 20 以后,应用接口响应依旧非常迅速。


但等应用真正上线时,却发生了重大事故,这是因为接口返回的都是无法使用的数据。


其问题原因也比较好定位,就是项目中使用了熔断。在压测的时候,接口直接超出服务能力,触发熔断了,但是压测并没有对接口响应的正确性做判断,造成了非常低级的错误。


优化的理论方法


理论方法有很多,如木桶理论、基础测试、Amdahal定律等等。


1、木桶理论

一只木桶若想要装最多的水,则需要每块木板都一样长而且没有破损才行。如果有一块木板不满足条件,那么这只桶就无法装最多的水。


能够装多少水,取决于最短的那块木板,而不是最长的那一块。


木桶效应在解释系统性能上,也非常适合。组成系统的组件,在速度上是良莠不齐的。系统的整体性能,就取决于系统中最慢的组件。


比如,在数据库应用中,制约性能最严重的是硬盘的 I/O 问题,也就是说,硬盘是这个场景下的短板,我们首要的任务就是补齐这个短板。


2、基准测试、预热

基准测试(Benchmark)并不是简单的性能测试,是用来测试某个程序的最佳性能。


应用接口往往在刚启动后都有短暂的超时。在测试之前,需要对应用进行预热,消除 JIT 编译器等因素的影响。而在 Java 里就有一个组件,即 JMH,就可以消除这些差异。


优化注意事项


1、把性能分析放在第一位而不是性能优化

在优化的时候不能凭借对代码的熟悉来猜测系统的问题所在,一般来说,复杂的业务系统往往有多个影响因素,我们应该将性能分析放在第一位,而不是把性能优化放在第一位。


进行性能优化时,我们一般会把分析后的结果排一个优先级(根据难度和影响程度),从大处着手,首先击破影响最大的点,然后将其他影响因素逐一击破。


有些优化会引入新的性能问题,有时候这些新问题会引起更严重的性能下降,你需要评估这个连锁反应,确保这种优化确实需要,同时需要使用数字去衡量这个过程,而不是靠感觉猜想。


2、进行大量试验,不依靠小数据量

个体请求的小批量数据,可参考价值并不是非常大。响应时间可能因用户的数据而异,也可能取决于设备和网络条件。


合理的做法,是从统计数据中找到一些规律,比如上面所提到的平均响应时间、TP 值等,甚至是响应时间分布的直方图,这些都能够帮我们评估性能质量。


3、不要过早优化和过度的优化

虽然性能优化有这么多好处,但并不代表我们要把每个地方都做到极致,性能优化也是要有限度的。程序要运行地正确,要比程序运行得更快还要困难。


计算机科学的鼻祖"Donald Knuth" 曾说:“过早的优化是万恶之源”,就是这个道理。


正确的做法是,项目开发和性能优化,应该作为两个独立的步骤进行,要做性能优化,要等到整个项目的架构和功能大体进入稳定状态时再进行。


4、保持良好的编程习惯


相关文章
|
6天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
22 6
|
8天前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
14天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
33 2
|
16天前
|
Java 数据库连接 数据库
优化之路:Java连接池技术助力数据库性能飞跃
在Java应用开发中,数据库操作常成为性能瓶颈。频繁的数据库连接建立和断开增加了系统开销,导致性能下降。本文通过问题解答形式,深入探讨Java连接池技术如何通过复用数据库连接,显著减少连接开销,提升系统性能。文章详细介绍了连接池的优势、选择标准、使用方法及优化策略,帮助开发者实现数据库性能的飞跃。
23 4
|
14天前
|
存储 Java 开发者
成功优化!Java 基础 Docker 镜像从 674MB 缩减到 58MB 的经验分享
本文分享了如何通过 jlink 和 jdeps 工具将 Java 基础 Docker 镜像从 674MB 优化至 58MB 的经验。首先介绍了选择合适的基础镜像的重要性,然后详细讲解了使用 jlink 构建自定义 JRE 镜像的方法,并通过 jdeps 自动化模块依赖分析,最终实现了镜像的大幅缩减。此外,文章还提供了实用的 .dockerignore 文件技巧和选择安全、兼容的基础镜像的建议,帮助开发者提升镜像优化的效果。
|
14天前
|
Java 数据库连接 数据库
Java连接池在数据库性能优化中的重要作用。连接池通过预先创建和管理数据库连接,避免了频繁创建和关闭连接的开销
本文深入探讨了Java连接池在数据库性能优化中的重要作用。连接池通过预先创建和管理数据库连接,避免了频繁创建和关闭连接的开销,显著提升了系统的响应速度和吞吐量。文章介绍了连接池的工作原理,并以HikariCP为例,展示了如何在Java应用中使用连接池。通过合理配置和优化,连接池技术能够有效提升应用性能。
31 1
|
15天前
|
Java 关系型数据库 数据库
面向对象设计原则在Java中的实现与案例分析
【10月更文挑战第25天】本文通过Java语言的具体实现和案例分析,详细介绍了面向对象设计的五大核心原则:单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则帮助开发者构建更加灵活、可维护和可扩展的系统,不仅适用于Java,也适用于其他面向对象编程语言。
10 2
|
19天前
|
缓存 前端开发 JavaScript
9大高性能优化经验总结,Java高级岗必备技能,强烈建议收藏
关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。本文介绍了9种性能优化方法,涵盖代码优化、数据库优化、连接池调优、架构层面优化、分布式缓存、异步化、Web前端优化、服务化、硬件升级、搜索引擎和产品逻辑优化。欢迎留言交流。
|
16天前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
18天前
|
存储 缓存 Java
Java应用瘦身记:Docker镜像从674MB优化至58MB的实践指南
【10月更文挑战第22天】 在容器化时代,Docker镜像的大小直接影响到应用的部署速度和运行效率。一个轻量级的Docker镜像可以减少存储成本、加快启动时间,并提高资源利用率。本文将分享如何将一个Java基础Docker镜像从674MB缩减到58MB的实践经验。
29 1