从java开发的视角谈性能分析与优化

1. 陷井

1.1 街灯效应

一天晚上,一个警察看到一个醉汉在路灯下的地面上找东西,问他在找什么。醉汉回答说他钥匙丢了。警察看了看也找不到,就问他:“你确定你钥匙是在这儿丢的,就在路灯下?”醉汉说:“不,但是这儿的光是最亮的”。

我们的对世界的认知有已知的已知,已知的未知,和未知的未知。已知的未知不可怕,即使我们不知道,也可以利用现在的知识网络检索到相关的信息;可怕的是未知的未知,当我们不知道“它”而“它”出现时,我们可能就束手无策了,这也意味着我们要扩充知识广度。

比如如果我们只知道加机器可以解决性能问题,出现性能问题时,我们只知道加机器;当加机器解决不了问题时,我们就不知道怎么办了。

1.2 在取得数据前,不要把事情理论化

在取得数据之前,把事情理论化是一个严重的错误。不理智的人扭曲事实来适应理论,而不是改变理论来适应事实。

《性能之巅》引自《波希米亚丑闻》

同样现象的问题,原因可能有多种,根据问题现象我们会猜测可能的原因。但如果猜测后不加验证就确认,就根据猜测去解决,可能是朝着一个错误的方向,徒劳无功;或是侥幸解决了问题,但可能掩盖了事实的真相。

2. 性能分析的方向

2.1 性能的指标

衡量系统性能的指标有许多,最主要的应该是以下三个

  1. 延时:从用户角度来说,延时是他们唯一关注的性能指标,低延时即高性能;从服务端角度来看,能为绝大多用户(如99%)提供低延时服务即高性能。
  2. TPS:对大多系统来说,每秒处理事务的数量是衡量性能的主要标准,TPS越高,意味着系统的处理能力越强,性能也就越好。
  3. 传输速率:一般来说,TPS与传输速率也越高;但如果两个请求,一个数据大小是100B,一个数据大小是10K,用TPS去对比他们的性能,显然是不公平的;所以一般我们也会通过传输速率来衡量系统性的性能。

2.2 性能问题原因和应对措施

性能问题的出现,主要有四类,缺陷、资源竞争、资源不足、资源利用不充分。我们所要做的对症下药:

  1. 修复程序缺陷,如使用合适的数据结构和算法,降低非必要的开销
  2. 降低资源的竞争,如使用合适的调度算法,减小互斥的范围
  3. 增加资源,通过提升配置和资源转换等手段消灭资源瓶颈
  4. 资源利用不充分看起来与资源不足互斥,但实际是另一种性能问题。如适合利用多线程加速的场景,使用单线程执行,这时可能就是资源利用不充分的情况。或是在资源闲忙差比较大时,通过合理的资源转换,更充分地利用资源,比如通过内存缓存减少重复IO和计算,利用CPU压缩减少内存或IO。

2.3 发现性能瓶颈

2.3.1 监控

要做性能优化,首先要明白性能问题在哪,只有定位到问题,才能去分析解决。可以借助系统监控工具(如Grafana )、链路追踪工具(如skywalking、Zipkin)去快速发现、追踪问题。

2.3.2 定位瓶颈

现在大多系统基本都是流水线模型,解决性能问题的核心是定位瓶颈,通过解决瓶颈来提升性能。在分析时有两点我们需要注意:

a. 确定什么需要优化,响应时间 × 请求频率

  1. 优化时首先要考虑的加速比,我们优化时尽量先解决能最大程度提供加速比的性能点。 比如一个请求读数据耗时耗时100ms,处理数据耗时10ms,即使我们将处理数据时间优化为0,对这个请求的提升也不到10%;但如果将数据读取的消耗降至20ms,整个请求就提升了300%。
  2. 在确定一个问题并解决后,一定要进行再次验证确认。通常旧的问题解决后,可能会让一些之前没出现的问题暴露出来。

性能分析有两种情况:

  1. 之前性能还ok,最近忽然慢了。
  2. 大家一直都知道这个很慢,现在我们想让他更快一些。

这两种情况虽然我们最终的分析手段是一样的,但我们的步骤可能会有些差异。

针对第一种情况,我们可以从最近的变更入手,相对精准地缩小分析范围,然后通过回滚等方式去验证。但有时变更导致的性能问题不一定是单独的变更导致的,可能是变更+其他因素共同导致的这个问题, 这时也要我们系统地分析性能的问题。

第二种情况,我们可以借助监控和压测工具,逐步定位性能的瓶颈。

3. 分析工具与方法

出现性能问题,大多可以通过资源的利用率体现出来

3.1 cpu

整体 cpu 使用情况,

top

 

若需要看具体进程,可执行(可以通过交互方式 H 查看线程分析情况,或执行top -Hp)

top -p

因现在cpu一般是多核,有时看整体cpu,cpu整体利用率可能不高。可能是单核的cpu瓶颈导致的。这时需要观察下单核cpu使用情况,可以使用

mpstat -P ALL 1 100

在发现cpu瓶颈后,可以确定进程和线程。

之后可以借助jps和jstack分析指定线程,准确定位cpu瓶颈的原因。

3.2 内存

free -h 可以查看机器当前内存的使用情况,一般会输出两行

mem表示物理内存,如果剩余内存很低了,那就说明内存不够用或存在内在滥用。若内存不够则升级内存,若使用的内存与期望不符则要考虑从程序原因入手了。

swap表示交换空间,是系统临时使用磁盘做内存的手段,这一行的used列最好为0。若不为0且与期望不符,可查看vm.swappiness,视情况将vm.swappiness设置为0(永远不使用交换空间)或1(当物理内存剩余量小1%时才使用交换空间),尽量避免使用交换空间。

3.3 IO

3.3.1 磁盘

磁盘出现性能问题主要有如下原因:

  • 磁盘利用率过高,需要频繁进行碎片整理
  • 大量IO
  • 内存不足,导致系统文件缓存命中率降低

磁盘利用率,可以通过 df -h 查看磁盘使用情况,若磁盘利用率高,可通过 du -d 1 -h(-d表示查看目深度)各个目录占用的空间大小。当磁盘出现不合理的空间占用时,可以用于定位大文件所在的位置。

磁盘读写情况可以通过 iostat -m 1 100 查看当前一段时间磁盘io读写情况,若出量大io读写,可以进一步通过iotop -oP(可能过左右方向键按磁盘读写排序)定位进程。

文件系统缓存命中率可以通过cachetop查看,若命中率较期望地低,可查看内存是否被其他应用抢占。

3.3.2 网络

网络对性能的影响主要在于带宽和连接

netstat -s 查看网络流量的统计信息

nload 查看当前网络流量速率

nethogs 查看进程的网络流量

磁盘IO和网络IO一般是耗时最多的地方,IO优化的方式主要有以下几点:

  • 通过缓存等手段降低重复的IO读取
  • 通过适合的策略合并小IO,

3.4 其他

uptime 查看系统负载

dmesg 查看系统事件

sar 系统活动报告

4.一些实践

    后续补充

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值