zoukankan      html  css  js  c++  java
  • 《Java性能优化权威指南》学习笔记

    编译

    编译是指生成机器码 即 二进制目标文件的过程。
    Java最初是转换为类文件,虚拟机将其转为字节码。
    运行时动态的转为机器码。

    JIT会在运行时,将调用次数超过阈值CompileThreshold的代码编译(由方法调用计数器计数)。

    JVM性能监控

    重要的垃圾收集数据
    堆大小。
    新生代、老年代、永久代大小
    Minor GC /Full GC 的持续时间、频率、空间回收量

    打印垃圾收集信息 -XX+PrintGCDetails

    可以启动时开启, 也可用jinfo 动态开启

    常用GC启动参数

    推荐 -XX:+PrintGCDetails -XX:+PrintGCDateStamps-Xloggc:<filename> -XX:+UseConcMarkSweepGC -Xmx400m -Xms400m -Xmn30m -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:G:/学习/gclog.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=G:/学习/dump.hprof

    资料:https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

    -XX:PrintGCTimeStamps 打印gc的时候打印时间戳
    -XX:+UseConcMarkSweepGC 使用cms垃圾回收器

    -Xmn30m 新生代30M 默认 SurvivorRatio 8, eden:s0:s1为8:1:1,所以新生代为9,即30m*0.9=27m

    MetaspaceSize 为本地内存。 非堆。
    -Xmx400m -Xms400m 最大堆内存 400M,最小堆内存400M, 老年代=400m-30m=370m

    jmap -head jpsid
    在这里插入图片描述

    收集的时候打印时间戳

    -XX:+PrintGCTImeStamps   启动秒数
    -XX:+PrintGCDateStamps  时间戳
    

    内存分布
    图片来源于网络
    Memory Pools
    在这里插入图片描述

    新生代

    Minor GC
    GC后 Eden几乎是空的。
    大多数新对象分配在Eden,大对象可能直接分配到老年代。(-XX:PretenureSizeThreshold
    MonorailGC后 ,两个Survivor交换角色。
    “足够老”的存活对象提升到老年代。
    用到复制算法。
    MinorGC过程中,Survivor(to)可能不足以容纳Eden+另一个Survivor(from)中的存活对象。此时就需要将Surviv偶然中的存活对象溢出?多余的对象转移到老年代–过早提升(Premature Promotion)。 — 如果老年代满了,无法容纳更大对象。(提升失败),minor GC后会导致Full GC.

    Minor GC:Eden+to 存活对象–> to 不够? ----> 老年代 不够? ----> Full GC

    老年代

    “足够老”的存活对象提升到老年代。

    永久代

    类加载 ,将类的源数据信息加载到永久代(jdk8以下)
    永久代满,引发垃圾收集-Full GC.
    当需要加载其他类而空间不足,未使用的类就会从永久代中被卸载。
    永久代垃圾回收不是stop-the-world
    相关参数: -XX:PermSize 、 -XX:MaxPerSize

    垃圾回收器

    分代垃圾收集器

    基于以下观察事实:

    1. 大多数分配对象朝生夕死。
    2. 存活时间久的对象很少引用存活时间短的对象。
    分代名称 内存占用 垃圾收集频率 特点
    新生代 minorGC,多次躲过回收后晋升到老年代
    老年代 FullGC执行频率低,但是执行时间长。尽量
    永久代 废弃常量和无用类

    Serial收集器

    只使用一个处理器
    minor GC 、 Full GC都 stop-the-world.
    标记清除、标记压缩

    适用于 对停顿时间要求不高,多个JVM实例在一台机器上。

    Parellel收集器-吞吐量

    吞吐量大。
    尽最大可能收集。
    Minor GC 并行。
    Full GC 并行。

    CMS收集器-低延迟

    停顿少,低延迟
    减少stop-the-world时间。

    初始标记 a 并发标记 b 重新标记 c 并发清除 d
    短暂停顿,标记GC Roots可达对象① 标记可从①对象达到的存活对象 再次停顿,重新标记b阶段导致未被标记的存活对象 清除整个Java堆

    G1收集器-分代、垃圾优先

    分代
    优先回收垃圾最多的区域。

    JVM性能调优

    关注稳定状态下 内存使用,程序延迟,吞吐量

    选择JVM运行模式

    client、server

    垃圾收集器

    吞吐量、延迟、内存占用 三选二,因为不能三者都满足。

    调整内存大小

    调整JVM堆布局

    调整新生代、老年代、永久代大小

    初始堆空间大小配置

    名称 设置参数 说明
    Java堆 -Xms和-Xmx 3-4倍FullGC后老年代空间量
    永久代 -XX:permSize和-XX:MaxPermSize 1.2-1.5倍~
    新生代 -Xmn 1-1.5倍~
    老年代 Java堆大小减新生代大小 2-3倍~

    Survivor

    Survivor太小,导致to无法存放所有从Eden空间和“From”空间复制来的活跃对象,导致提升到老年代。 加速老年代内存消耗,提前Full GC.

    -XX:SurvivorRatio=<ratio>

    ratio表示单个survivor空间与Eden空间大小的比率。
    如果是8,则表示 from:to:eden = 1:1:8
    所以调大Survivor需要降低ratio。

    survivor空间大小 = -Xmn/(-XX:SurvivorRatio=+2)

    晋升

    对象提升至老年代。
    晋升阈值就是对象年龄。对象的年龄就是它所经历的Minor GC次数。
    【最大晋升阈值参数】-XX:MaxTenuringThreshold=<n>
    对象年龄超过n值将其提升到老年代。

    不建议将【最大晋升阈值】设置为0,这会导致刚分配的对象,会在接下来的Minor GC中直接从新生代晋升到老年代,导致老年代空间迅速增长以至于Full GC。

    不成熟的(未到年龄)的晋升解决方案是:使用SurvivorRatio增大Survivor空间

    当Survivor空间比较紧张,JVM会使用一个低于 最大晋升阈值(MaxTenuringThreshold)的值来保证目标Survivor空间的占用。

    注意:Survivor空间过小,导致JVM 内部计算的阈值过小,导致易晋升到老年代,导致Full GC频繁。

    监控晋升阈值

    参数:-XX:+PrintTenuringDistribution
    期望Survivor大小 小于 活下来的对象。导致Survivor空间溢出,提升对象到老年代。

    至少将Survivor增大到 【存活的Survivor大小】 
    

    调整Survivor空间的容量

    原则:调整Survivor空间的时候,如果新生代空间大小不变,增大Survivor则减少Eden。
    因此,增大Survivor的同时,保持Eden空间不变,需要增大新生代空间。

    理想状态:晋升阈值等于最大晋升阈值

    如果Minor GC时间过长,就要减少新生代空间大小。

    调整目标Survivor空间占用

    尝试Minor GC之后仍然维持的Survivor空间占用

    参数:-XX:TargetSurvivorRatio=<percent>

    新生代
    新生代大小决定了应用平均延迟
    如果平均Minor GC持续时间大于应用程序平均延迟性要求,可以适当减小新生代空间大小;
    如果Minor GC频率大于应用程序平均延迟性要求,可以适当增大新生代空间;
    老年代
    老年代大小决定了应用最差延迟
    FullGC频率大于应用程序最大FullGC频率要求,可以适当增大老年代空间大小;
    FullGC持续时间大于应用程序最差延迟性要求,可以使用CMS垃圾收集器;

  • 相关阅读:
    Muddy Fields
    LightOJ 1321
    LightOJ 1085
    LightOJ 1278
    LightOJ 1341
    LightOJ 1340
    vijos 1426 背包+hash
    vijos 1071 01背包+输出路径
    vijos 1907 DP+滚动数组
    vijos 1037 背包+标记
  • 原文地址:https://www.cnblogs.com/thewindkee/p/12873114.html
Copyright © 2011-2022 走看看