JVM优化-上篇

Posted 弥之猫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM优化-上篇相关的知识,希望对你有一定的参考价值。


什么是系统性能调优?对此每个人都有自己理解,本文重点说明在调优过程中对jvm相关知识的使用。

1.系统优化

系统调优,通常我们接触到的有硬件调优、软件调优、数据库调优。

1.1硬件调优

一般来说就是硬件基础设施的调优,以lunix为例来说,一般有:

1)TCP通讯参数调整(/etc/sysctl.conf)

TCP通讯参数调整(/etc/sysctl.conf)kernel.sem= 2000 2048000 32 1024//每个信号对象集的最大信号对象数;kernel.shmmax=1073741824//最大共享内存段大小;kernel.msgmni=2000//整个系统共享内存段的最大数目kernel.msgmax=81920//限制一条消息的最大长度;kernel.msgmnb=163840//限制一个队列的最大长度;net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_tw_recycle = 0net.ipv4.tcp_syncookies = 1//表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击, net.ipv4.tcp_fin_timeout = 10//表示如果套接字由本端要求关闭,这个参数决定了保持在FIN-WAIT-2状态的时间,默认是60,降低这个值以提高系统性能net.ipv4.tcp_keepalive_time = 1200net.ipv4.tcp_keepalive_intvl = 2net.ipv4.tcp_keepalive_probes = 2net.ipv4.tcp_max_syn_backlog = 8192//定义backlog队列容纳的最大半连接数,如果配置高可以设置的更高;net.ipv4.tcp_max_tw_buckets = 8000net.ipv4.ip_local_port_range=10000 20480net.ipv4.tcp_syn_retries=3

2)修改文件句柄数(/etc/security/limits.conf)

soft nproc :单个用户可用的最大进程数量(超过会警告);hard nproc:单个用户可用的最大进程数量(超过会报错);soft nofile :可打开的文件描述符的最大数(超过会警告);hard nofile :可打开的文件描述符的最大数(超过会报错);

3)修改用户可用最大线程数(/etc/security/limits.d/90-nproc.conf)

* soft nproc 102400

1.2数据库调优

数据库优化目前有四种,即查询语句优化、索引优化、表结构优化、存储方式优化。

  • 查询语句优化:避免过多的表关联,注意where中的字段顺序,缩小数据范围。

  • 索引优化:合理分析并设置、调整索引。

  • 表结构优化:若数据量过大,纵向或者横向拆分表。纵向拆,将前n个字段放在一个表,后面m个放另一个表。横向,满足一定条件的数据放一个表。

  • 存储方式优化:通过不同的存储空间或者表分区,将数据存放在不同的存储区域。

由于数据库调优不是本文重点,就不过多赘述了。

2.JVM调优

JVM调优,主要的聚焦点可以认为是在不断调整内存参数、合理使用GC直到程序符合我们的要求;其中GC的调优又是我们的调优重点。在调优之前,让我们先熟悉以下这些概念。

2.1通用术语

•串行:它只有一条线程,在运行的时候需要暂停用户程序(stop the world)。

•并行:它有多条GC线程,在运行时也需要暂停用户程序(stop the world)。

•并发:它有一条或多条GC线程,且它需要在部分阶段暂停用户程序(stop the world),部分阶段与用户程序并发执行。

•STW,停止用户线程的执行。

2.2内存的分区

运行时的内存分区有方法区、堆、栈、程序计数器、本地方法栈,其中堆、方法区是所有线程共享的,栈和程序技术器是线程私有的。其中垃圾回收的作用域是堆内存。
堆主要分为新生代、老年代、永久代或元空间。 方法区为逻辑区域,jdk8之前存放在永久代,jdk8之后,直接存放在元空间(位于本地内存,即堆外内存、非堆内存)。
新生代一般分为伊甸园区、from幸存者区、to幸存者区;需要关注,新的对象实例一般在伊甸园区,但是并不绝对。eden:survovir:survivor=8:1:1。设置survivor是为了减少送到老年代的对象,设置两个Survivor区是为了解决碎片问题(复制算法。)。
2.3判断是否可以回收的算法
  • 引用计数法:给对象添加上一个引用计数器,当对象增加一个引用时就加1,当一个引用失效时就减1,当引用计数为0时,该对象就可以被回收;

  • 可达性分析:对每个对象,都分析一下谁引用了它,然后一层一层分析,看最终是否有GC Roots引用了它。

判断一个对象是否能够回收的过程(两步):1.找到GC Roots不可达的对象,看其是否重写了finalize()方法或者调用了finalize()方法,如果都没有就放入F-Queue中;2.再次进行标记,如果这些对象还没有与GC Roots建立连接,则直接回收。
2.4垃圾回收的算法
  • 复制算法:是将堆内存分为两个相等的区域,每次只使用其中的一块,当其中一块区域满的时候,就会将存活的对象复制到另一个区域,然后将该区域清理;优点是简单高效,不会存在内存碎片问题;缺点内存利用率低;

  • 标记-整理:和复制算法一样,将所有的存活对象标记出来,然后将所有的对象移动到内存的一端;老年代使用的就是标记-整理算法;缺陷是需要移动大量的对象,效率不高。

  • 标记-清除:将所有待回收的对象标记出来,然后一起清理;缺陷是标记和清理的效率都不高,可能产生大量的内存碎片。

  • 分代回收算法:根据不同的年代选取不同的垃圾回收算法,年轻代使用复制算法,老年代使用标记-清除算法或者标记-整理算法。

2.5垃圾回收类型
  • YoungGC或MinorGC:大多数情况下,对象会优先分配在Eden区。
    当Eden区内存不足时,虚拟机会发起一次Minor GC;
    如果一个对象在Eden区中,并且在一次Minor GC后仍然存活,也没有进入老年代中。
    被复制到一个Survivor中,那么它的年龄被记为1,以后每经历过一轮的Minor GC,年龄就增长一岁。
    达到一定年龄后就会进入老年代 ;
    需注意如果survivor中年龄一岁+年龄两岁的对象占比超过survivor空间的百分之50,则两岁及以上的所有对象统统进入老年代。
  • MajorGC:
    Major GC 是清理老年代。
  • FullGC:Full GC 是清理整个堆空间—包括年轻代和老年代。
    Major GC发生过程常常伴随一次Minor,因此Full GC可以看做是Major GC+Minor GC共同进行的一整个过程,清理了整个堆上的对象。
    但是,一般情况下我们可以认为FullGC约等于MajorGC,但是在CMS垃圾收集器中,他们会有明显的差别。
2.6垃圾收集器

垃圾收集器分为三类:
  • 串行搜集器(serial collector):Serial、Serial Old就是典型的串行收集器。它只有一条GC线程,它在运行的时候需要暂停用户程序(stop the world)。
  • 并行搜集器(parallel collector):PerNew、Parallel Scavenge、ParallelOld是典型并行收集器,是典型的多条GC线程,且它也需要暂停用户程序(stop the world)。
  • 并发搜集器(concurrent collector):CMS、G1是典型的并发收集器,它有一条或多条GC线程,且它需要在部分阶段暂停用户程序(stop the world),部分阶段与用户程序并发执行。

以上对于JVM的基础知识有了一些了解,下一阶段继续介绍如何对于内存大小的调优以及如何选择合适的垃圾回收器。


以上是关于JVM优化-上篇的主要内容,如果未能解决你的问题,请参考以下文章

JVM技术专题 Java各种类型对象占用内存情况分析「上篇」

JVM技术专题垃圾回收认知和调优的“思南(司南)“「上篇」

分析定位占用CPU资源高的JVM线程

java 简单的代码片段,展示如何将javaagent附加到运行JVM进程

优化 C# 代码片段、ObservableCollection 和 AddRange

JVM技术专题精心准备了一套JVM分析工具的锦囊「上篇」