JVM
JVM内存结构
垃圾回收算法
- 思想:枚举根节点,做可达性分析
- 根节点:类加载器、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=<N> 多少个GC线程(CPU<8?N=CPU:N=5/8) Parallel Collector Ergonomics,会按以下顺序自动调整 -XX:MaxGCPauseMillis=<N> -XX:GCTimeRatio=<N> -Xmx<N> 动态内存调整 -XX:YoungGenerationSizelncrement=<Y> #20% -XX:TenuredGenerationSizeLncrement=<T> #20% -XX:AdaptiveSizeDecrementScaleFactor=<D>
-
并发收集器: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
收集器调优指南
Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide
并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。适合科学计算、后台处理等弱交互场景
并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),垃圾收集线程在执行的时候不会停顿用户线程的运行。适合对响应时间有要求的场景,比如Web
停顿时间:垃圾收集器做垃圾回收中断应用执行的时间 -XX:MaxGCPauseMillis
吞吐量:花在垃圾收集的时间和花在应用时间的占比 -XX:GCTimaRatio=<n>,垃圾收集时间占:1/(1+n)
GC日志格式
日志参数
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:$CATALINA_HOME/logs/gc.log -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution
ParallelGC调优
- 打印GC日志
- 根据日志得到关键性能指标(GCViewer)
- 分析GC原因,调优JVM参数
调优测试
ParallelGC调优指导原则
- 除非确定,否则不要设置最大堆内存
- 优先设置吞吐量目标
- 如果吞吐量目标达不到,调大最大内存,不能让OS使用Swap,如果仍然达不到,降低目标
- 吞吐量能达到,GC时间太长,设置停顿时间的目标
- 初始设置
-XX:DisableExplictGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_HOME/logs/ -XX:+PrintGCDetails -XX:PrintGCTimeStamps -XX:+PringGCDateSamps -Xloggc:$CATALINA_HOME/logs/gc.log
-
设置Metaspace大小
-XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=64M
-
添加吞吐量和停顿时间参数
-XX:GCTimeRatio=99 -XX:MaxGCPauseMillis=100
-
修改动态扩容增量
-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<String> list = new ArrayList<String>(10); Map<String,String> map = new HashMap<String,String>(20);
-
ArrayList遍历快,LinkedList增删快
-
集合遍历尽量减少重复计算
for(int i=0,len=list.size();i<len;i++){}
-
使用Entry遍历Map
for(Map.Entry<String,String> 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);推荐