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= 多少个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
[收集器调优指南](https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/collectors.html)
并行(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调优
打印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 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);推荐
完善中。。。