JVM面试-性能调优问题逻辑梳理

JVM面试-调优问题逻辑梳理

1.首先回答性能优化硬件方面。

存储性能优化
尽量使用SSD固态硬盘,加大内存。

2.其次考虑JVM及代码层次的优化

JVM调优的本质:
并不是显著的提高系统性能,不是说你调了,性能就能提升几倍或者上十倍,JVM调优,主要调的是稳定。如果你的系统出现了频繁的垃圾回收,这个时候系统是不稳定的,所以需要我们来进行JVM调优,调整垃圾回收的频次。
GC调优原则
1、大多数的java应用不需要GC调优
2、大部分需要GC调优的的,不是参数问题,是代码问题
3、在实际使用中,分析GC情况优化代码比优化GC参数要多得多;
4、GC调优是最后的手段
调优的目的
GC的时间够小
GC的次数够少
发生Full GC的周期足够的长,时间合理,最好是不发生。
注:如果满足下面的指标,则一般不需要进行GC:
Minor GC执行时间不到50ms;
Minor GC执行不频繁,约10秒一次;
Full GC执行时间不到1s;
Full GC执行频率不算频繁,不低于10分钟1次;

调优步骤
日志分析
1,监控GC的状态
使用各种JVM工具,查看当前日志,分析当前JVM参数设置,并且分析当前堆内存快照和gc日志,根据实际的各区域内存划分和GC执行时间,觉得是否进行优化;
2,分析结果,判断是否需要优化
如果各项参数设置合理,系统没有超时日志出现,GC频率不高,GC耗时不高,那么没有必要进行GC优化;如果GC时间超过1-3秒,或者频繁GC,则必须优化;
3,调整GC类型和内存分配
如果内存分配过大或过小,或者采用的GC收集器比较慢,则应该优先调整这些参数,并且先找1台或几台机器进行beta,然后比较优化过的机器和没有优化的机器的性能对比,并有针对性的做出最后选择;
4,不断的分析和调整
通过不断的试验和试错,分析并找到最合适的参数
5,全面应用参数
如果找到了最合适的参数,则将这些参数应用到所有服务器,并进行后续跟踪。
阅读GC日志
主要关注MinorGC和FullGC 的回收效率(回收前大小和回收比较)、回收的时间。

利用JVM调优命令及工具

Sun JDK监控和故障处理命令有jps jstat jmap jhat jstack jinfo

jps,JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。
jstat,JVM statistics Monitoring是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
jmap,JVM Memory Map命令用于生成heap dump文件
jhat,JVM Heap Analysis Tool命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看
jstack,用于生成java虚拟机当前时刻的线程快照。
jinfo,JVM Configuration info 这个命令作用是实时查看和调整虚拟机运行参数。
调优工具
常用调优工具分为两类,jdk自带监控工具:jconsole和jvisualvm,第三方有:MAT(Memory Analyzer Tool)、GChisto。

jconsole,Java Monitoring and Management Console是从java5开始,在JDK中自带的java监控和管理控制台,用于对JVM中内存,线程和类等的监控
jvisualvm,jdk自带全能工具,可以分析内存快照、线程快照;监控内存变化、GC变化等。
MAT,Memory Analyzer Tool,一个基于Eclipse的内存分析工具,是一个快速、功能丰富的Java heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗
GChisto,一款专业分析gc日志的工具

生产服务器推荐开启
-XX:-HeapDumpOnOutOfMemoryError 默认关闭,建议开启,在java.lang.OutOfMemoryError 异常出现时,输出一个dump.core文件,记录当时的堆内存快照。
-XX:HeapDumpPath=./java_pid.hprof 用来设置堆内存快照的存储文件路径,默认是java进程启动位置,。
调优之前开启、调优之后关闭
-XX:+PrintGC
调试跟踪之 打印简单的GC信息参数:
-XX:+PrintGCDetails, +XX:+PrintGCTimeStamps
打印详细的GC信息
-Xlogger:logpath
设置gc的日志路,如: -Xlogger:log/gc.log, 将gc.log的路径设置到当前目录的log目录下.
应用场景: 将gc的日志独立写入日志文件,将GC日志与系统业务日志进行了分离,方便开发人员进行追踪分析。

-XX:+PrintHeapAtGC, 打印推信息
参数设置: -XX:+PrintHeapAtGC
应用场景: 获取Heap在每次垃圾回收前后的使用状况
-XX:+TraceClassLoading
参数方法: -XX:+TraceClassLoading
应用场景: 在系统控制台信息中看到class加载的过程和具体的class信息,可用以分析类的加载顺序以及是否可进行精简操作。
-XX:+DisableExplicitGC禁止在运行期显式地调用System.gc()

例子:
以参数-Xms5m -Xmx5m -XX:+PrintGCDetails -XX:+UseSerialGC为例:
[DefNew: 1855K->1855K(1856K), 0.0000148 secs][Tenured: 2815K->4095K(4096K), 0.0134819 secs] 4671K
DefNew指明了收集器类型,而且说明了收集发生在新生代。
1855K->1855K(1856K)表示,回收前 新生代占用1855K,回收后占用1855K,新生代大小1856K。
0.0000148 secs 表明新生代回收耗时。
Tenured表明收集发生在老年代
2815K->4095K(4096K), 0.0134819 secs:含义同新生代
最后的4671K指明堆的大小。

根据日志分析,是否需要修改堆大小,survivor区占比,甚至GC垃圾回收器类型。

  • 补充具体调优例子。

常用的性能优化手段

避免过早优化
不应该把大量的时间耗费在小的性能改进上,过早考虑优化是所有噩梦的根源。
所以,我们应该编写清晰,直接,易读和易理解的代码,真正的优化应该留到以后,等到性能分析表明优化措施有巨大的收益时再进行。
但是过早优化,不表示我们就可以随便写代码,还是需要注重编写高效优雅的代码。
进行系统性能测试
所有的性能调优,都有应该建立在性能测试的基础上,直觉很重要,但是要用数据说话,可以推测,但是要通过测试求证。
寻找系统瓶颈,分而治之,逐步优化
性能测试后,对整个请求经历的各个环节进行分析,排查出现性能瓶颈的地方,定位问题,分析影响性能的的主要因素是什么?内存、磁盘IO、网络、CPU,还是代码问题?架构设计不足?或者确实是系统资源不足?
前端优化常用手段
浏览器/App
减少请求数
合并CSS,Js,图片,
生产服务器提供的all的js文件
http中的keep-alive(http1.1中默认开启)包括nginx
使用客户端缓冲
静态资源文件(css、图标等)缓存在浏览器中,有关的属性Cache-Control(相对时间)和Expires
如果文件发生了变化,需要更新,则通过改变文件名来解决。
启用压缩
浏览器(zip),压缩率80%以上。
减少网络传输量,但会给浏览器和服务器带来性能的压力,需要权衡使用。
资源文件加载顺序
css放在页面最上面,js放在最下面。这样页面的体验才会比较好。
浏览器会加载完CSS才会对页面进行渲染
JS只要加载后就会立刻执行。(有些JS可能执行时间比较长)
减少Cookie传输
cookie包含在每次的请求和响应中,因此哪些数据写入cookie需要慎重考虑(静态资源不需要放入cookie)
友好的提示(非技术手段)
有时候在前端给用户一个提示,就能收到良好的效果。毕竟用户需要的是不要不理他。
CDN加速
CDN,又称内容分发网络,本质是一个缓存,而且是将数据缓存在用户最近的地方。无法自行实现CDN的时候,可以根据经济实力考虑商用CDN服务。
反向代理缓存
将静态资源文件缓存在反向代理服务器上,一般是Nginx。
WEB组件分离
将js,css和图片文件放在不同的域名下。可以提高浏览器在下载web组件的并发数。因为浏览器在下载同一个域名的的数据存在并发数限制。
应用服务性能优化
缓存
网站性能优化第一定律:优先考虑使用缓存优化性能

优先原则:缓存离用户越近越好
缓存的基本原理和本质
缓存是将数据存在访问速度较高的介质中。可以减少数据访问的时间,同时避免重复计算。
合理使用缓存的准则
频繁修改的数据,尽量不要缓存,读写比2:1以上才有缓存的价值。
缓存一定是热点数据。
应用需要容忍一定时间的数据不一致。
缓存可用性问题,一般通过热备或者集群来解决。
分布式缓存与一致性哈希
以集群的方式提供缓存服务,有两种实现;
1、需要更新同步的分布式缓存,所有的服务器保存相同的缓存数据,带来的问题就是,缓存的数据量受限制,其次,数据要在所有的机器上同步,代价很大。
2、每台机器只缓存一部分数据,然后通过一定的算法选择缓存服务器。常见的余数hash算法存在当有服务器上下线的时候,大量缓存数据重建的问题。所以提出了一致性哈希算法。
一致性哈希:

  1. 首先求出服务器(节点)的哈希值,并将其配置到0~2的32次方的圆(continuum)上。
  2. 然后采用同样的方法求出存储数据的键的哈希值,并映射到相同的圆上。
  3. 然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。如果超过232仍然找不到服务器,就会保存到第一台服务器上。
    一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。
    数据倾斜:
    一致性哈希算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题,此时必然造成大量数据集中到Node A上,而只有极少量会定位到Node B上。为了解决这种数据倾斜问题,一致性哈希算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。具体做法可以在服务器ip或主机名的后面增加编号来实现。例如,可以为每台服务器计算三个虚拟节点,于是可以分别计算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值,于是形成六个虚拟节点:同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到“Node A#1”、“Node A#2”、“Node A#3”三个虚拟节点的数据均定位到Node A上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。
    集群
    可以很好的将用户的请求分配到多个机器处理,对总体性能有很大的提升
    异步
    同步和异步,阻塞和非阻塞

你可能感兴趣的:(个人笔记,JVM,面试,jvm,java)