Java调优总结

JVM

JVM内存结构

Java调优总结_第1张图片

垃圾回收算法

  • 思想:枚举根节点,做可达性分析
  • 根节点:类加载器、Thread、虚拟机栈的本地变量表、static成员、常量引用、本地方法栈的变量

标记清除算法

算法:是分为"标记"和”清除“两个阶段,首先标记出所有需要回收的对象,在标记完成后统一回收所有

缺点:效率不高,标记和清除两个过程的效率都不高;产生碎片,碎片太多会导致提前GC

复制算法

它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块,当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过得内存空间一次清理掉

优缺点:实现简单、运行高效,但是空间利用率低

标记整理算法

标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,让后直接清理掉端边界以外的内存

优缺点:没有了内存碎片,但是整理起来比较耗时

分代垃圾回收算法

Young区用复制算法

Old区用“标记-清除”或者“标记整理”算法

对象分配

  • 对象优先在Eden区分配
  • 大对象直接进入老年代:-XX:PretenureSizeThreshold
  • 长期存活对象进入老年代:-XX:MaxTenuringThreshold -XX:+PrintTenuringDistribution -XX:TargetSurvivorRatio

垃圾收集器

  • 串行收集器Serial:Serial、Serial Old

    -XX:+UseSerialGC -XX:+UseSerialOldGC
  • 并行收集器Paralle:Parallel Scavenge、Parallel Old,(是吞吐量优先收集器)

    -XX:+UseParallelGC 手动开启 (-XX:+UseParallelOldGC),Server模式默认开启
    -XX:ParallelGCThreads= 多少个GC线程(CPU<8?N=CPU:N=5/8)
    
    Parallel Collector Ergonomics,会按以下顺序自动调整
        -XX:MaxGCPauseMillis=
        -XX:GCTimeRatio=
        -Xmx
    动态内存调整
        -XX:YoungGenerationSizelncrement= #20%
        -XX:TenuredGenerationSizeLncrement= #20%
        -XX:AdaptiveSizeDecrementScaleFactor=
  • 并发收集器:Concurrent:CMS、G1,(是停顿时间优先收集器)

    CMS Collector(老年代收集器)
        并发收集
        低停顿 低延迟
    CMS垃圾收集过程
        1.CMS initial mark:初始标记Root,STW
        2.CMS concurrent mark:并发标记
        3.CMS-concurrent-preclean:并发预清理
        4.CMS remark:重新标记,STW
        5.CMS concurrent sweep:并发清除
        6.CMS-concurrent-reset:并发重置
    CMS缺点
        CPU敏感
        浮动垃圾
        空间碎片
    CMS相关参数
        -XX:ConcGCThreads:并发的GC线程数
        -XX:+UseCMSCompactAtFullCollection:FullGC之后做压缩
        -XX:CMSFullGCsBeforeCompaction:多少次FullGC之后压缩一次
        -XX:CMSInitiatingOccupancyFraction:触发FullGC
        -XX:+UseCMSInitiatingOccupancyOnly:是否动态可调
        -XX:+CMSScavengeBeforeRemark:FullGC之前先做YGC(YoungGC)
        -XX:+CMSClassUnloadingEnabled:启用回收Perm区
    ICMS
        适用于单核或双核(jdk8已弃用)
    -----------------------------------------------------------------------    
    G1 Collector(新生代和老年代收集器)
    简介:
        The Garbage-First (G1) collector is a server-style garbage collector, targeted for multi-processor machines with large memories. It meets garbage collection (GC) pause time goals with a high probability, while achieving high throughput. The G1 garbage collector is fully supported in Oracle JDK 7 update 4 and later releases. The G1 collector is designed for applications that:
        Can operate concurrently with applications threads like the CMS collector.
        Compact free space without lengthy GC induced pause times.
        Need more predictable GC pause durations.
        Do not want to sacrifice a lot of throughput performance.
        Do not require a much larger Java heap.
    G1的几个概念
        Region
        STAB:Snapshot-At-The-Beginning,它是通过Root Tracing得到的,GC开始时候存活对象的快照
        RSet:记录了其他的Region中的对象引用本Region中的对象关系,属于points-into结构(谁引用了我的对象)
        
    YoungGC
        新对象进入Eden区
        存活对象拷贝到Survivor区
        存活时间叨叨年龄阈值时,对象晋升到Old区
        
    MixedGC
        不是FullGC,回收所有Young区和部分Old区
        global concurrent marking
            1.Initial marking phase:标记GC Root,STW
            2.Root region scanning phase:标记存活Region
            3.Concurrent marking phase:标记存活的对象
            4.Remark phase:重新标记,STW
            5.Cleanup phase:部分STW
        MixedGC调优
            InitiatingHeapOccupancyPercent:占有率达到这个数值则触发global concurrent marking,默认45%
            G1HeapWastePercent:在global concurrent marking结束之后,可以知道区多少空间要被回收,在每次YGC之后和再次发生MixedGC之前,会检查垃圾占比是否达到此参数,只有达到了,下次才会发生MixedGC
            G1MixedGCLiveThresPercent:Old区的region被回收时存活对象占比
            G1MixedGCCountTarget:一次global concurrent marking之后,最多执行MixedGC的次数
            G1OldCSetRegionThresholdPercent:一次MixedGC中能被选入CSet的最多old区的region数量
    
    常用参数
        -XX:+UseG1GC #开启G1
        -XX:G1HeapRegionSize=n #region的大小,1-32M,2048个
        -XX:MaxGCPauseMillis=200 #最大停顿时间
        -XX:G1NewSizePercent、-XX:G1MaxNewSizePercent
        -XX:G1ReservePercent=10 #保留防止to space溢出
        -XX:ParallelGCThreads=n #SWT线程数
        -XX:ConcGCThreads=n #并发线程数=1/4*并行线程数
    G1最佳调试
        年轻代大小:避免使用-Xmn、-XX:NewRation等显示设置,Young区太小,会覆盖暂停时间目标
        暂停时间目标:暂停时间不要太严苛,其吞吐量目标是90%的应用程序时间和10%的垃圾回收时间,太严苛会直接影响到吞吐量
        
    需否需要切换到G1
        50%以上的堆被存活对象占用
        对象分配和晋升的速度变化非常大
        垃圾回收时间特别长,超过1S

    Concurrent Mark Sweep (CMS) Collector

    Garbage-First Garbage Collector Tuning

Java调优总结_第2张图片

[收集器调优指南](https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/collectors.html)

Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide

 并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。适合科学计算、后台处理等弱交互场景

 并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),垃圾收集线程在执行的时候不会停顿用户线程的运行。适合对响应时间有要求的场景,比如Web

 停顿时间:垃圾收集器做垃圾回收中断应用执行的时间 -XX:MaxGCPauseMillis

 吞吐量:花在垃圾收集的时间和花在应用时间的占比 -XX:GCTimaRatio=,垃圾收集时间占:1/(1+n)

GC日志格式

日志参数

-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:$CATALINA_HOME/logs/gc.log -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution

ParallelGC调优

  1. 打印GC日志
  2. 根据日志得到关键性能指标(GCViewer)
  3. 分析GC原因,调优JVM参数

调优测试

ParallelGC调优指导原则
ParallelGC调优先参考
  • 除非确定,否则不要设置最大堆内存
  • 优先设置吞吐量目标
  • 如果吞吐量目标达不到,调大最大内存,不能让OS使用Swap,如果仍然达不到,降低目标
  • 吞吐量能达到,GC时间太长,设置停顿时间的目标
  1. 初始设置
-XX:DisableExplictGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_HOME/logs/ -XX:+PrintGCDetails -XX:PrintGCTimeStamps -XX:+PringGCDateSamps -Xloggc:$CATALINA_HOME/logs/gc.log
  1. 设置Metaspace大小

    -XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=64M
  2. 添加吞吐量和停顿时间参数

    -XX:GCTimeRatio=99 -XX:MaxGCPauseMillis=100
  3. 修改动态扩容增量

    -XX:YoungGenerationSizelncrement=30 #30%

    G1调优

    相关参数
    -XX:+UseG1GC -Xms128M -XmX128M -XX:MetaspaceSize=64M -XX:MaxGCPauseMills=100 -XX:UseStringDeduplication -XX:StringDeduplicationAgeThreshold=3
    

Tomcat优化

  • 内存优化(略)
  • 线程优化
  • 配置优化

线程优化

tomcat/webapps/docs/config/http.html
maxConnections:The maximum number of connections that the server will accept and process at any given time.
acceptCount:The maximum queue length for incoming connection requests when all possible request processing threads are in use.
maxThreads:The maximum number of request processing threads to be created by this Connector, which therefore determines the maximum number of simultaneous requests that can be handled. 
minSpareThreads:The minimum number of threads always kept running. If not specified, the default of 10 is used.

配置优化

tomcat/webapps/docs/config/host.html
autoDeploy:This flag value indicates if Tomcat should check periodically for new or updated web applications while Tomcat is running.
tomcat/webapps/docs/config/http.html
enableLookups:false
tomcat/webapps/docs/config/context.html
reloadable:false
tomcat/conf/server.xml
protocol="HTTP/1.1"
Session优化,如果是JSP
session=false

Nginx优化

  • 增加工作线程数和并发连接数
  • 启用长连接
  • 启用缓存、压缩
  • 操作系统优化

配置线程数和并发连接数

worker_processes 4;#根据cpu个数
events {
    worker_connections 1024;#每一个进程打开的最大连接数,包括Nginx与客户端和Nginx与upstream之间的连接
    multi_accept on;#可以一次建立多个链接
    use epoll;
}

配置后端Server的长连接

upstream server_poll{
    server localhost:8080 weight=1 max_fails=2 fail_timeout=30s;
    server localhost:8081 weight=1 max_fails=2 fail_timeout=30s;
    keepalive 300;#300个长连接
}
location / {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_pass http://server_poll/;
}

配置压缩

gzip on;
gzip_http_version 1.1;
gzip_disable "MSIE[1-6]\.(?!.*SV1)";
gzip_proxied any;
gzip_types text/plain text/css application/javascrip application/x-javascript application/json application/xml application/vnd.ms-fontobject application/x-font-ttf application/svg+xml application/x-icon;
gzip_vary on;#Vary:Accept-Encoding
gzip_static on;#如果有压缩好的,直接使用

操作系统优化

配置文件:/etc/sysctl.conf
sysctl -w net.ipv4.tcp_syncookies=1#防止一个套接字在有过多试图连接到达时引起过载
sysctl -w net.core.somaxconn=1024#默认128,连接队列
sysctl -w net.ipv4.tcp_fin_timeout=10#timewait超时
sysctl -w net.ipv4.tcp_tw_reuse=1#os直接使用timewait的连接
sysctl -w net.ipv4.tcp_tw_recycle=0#回收禁用
其他优化
sendfile on;#减少文件在应用和内核之间拷贝
tcp_nopush on;#当数据包达到一定大小再发送
tcp_nodelay off;#有数据随时发送

代码优化

  • 尽量重用对象,不要循环创建对象,比如:for循环字符串拼接
  • 容器类初始化时指定长度

    List list = new ArrayList(10);
    Map map = new HashMap(20);
  • ArrayList遍历快,LinkedList增删快
  • 集合遍历尽量减少重复计算

    for(int i=0,len=list.size();i
  • 使用Entry遍历Map

    for(Map.Entry entry:map.entrySet()){
        String key = entry.getKey();
        String value = entry.getValue();
    }
  • String尽量少用正则表达式

    replace() VS replaceAll();
    split();
  • 大数组复制用System.arraycopy
  • 尽量使用基本类型,减少转换
  • 不手动调用Systemgc()
  • 及时清除过期对象的引用,防止内存泄漏
  • 尽量使用局部变量,减小变量的作用域
  • 尽量使用非同步容器 ,ArrayList VS Vector
  • 尽量减小同步作用范围,synchronized方法VS synchronized 代码块
  • ThreadLocal缓存线程不安全的对象(不用经常new对象),SimpleDateFormat
  • 尽量使用延迟加载,如:静态内部类单例模式
  • 减少使用反射,加缓存
  • 尽量使用连接池、线程池、对象池、缓存
  • 及时释放资源,I/O流、Socket、数据库连接
  • 慎用异常,不要用抛异常来表示正常的业务逻辑
  • 日志输出使用不同级别
  • 日志中参数拼接使用占位符

    log.info("orderId:" + orderId);不推荐
    log.info("orderId:{}" orderId);推荐

完善中。。。

你可能感兴趣的:(java,jvm,nginx)