SlideShare a Scribd company logo
1 of 43
Java性能调优浅谈
@Will
1
提纲
• 一些相关原理
• 性能测量指标
• 性能优化模式
• 代码调优
• JVM调优
• …
2
性能测量指标 - 1
• 各类资源消耗情况:
 磁盘IO
 内存占用
 CPU
 数据库
 网络
 锁竞争
 …
3
性能测量指标 - 2
4
性能测量指标 - 3
• 其他最常用的两个指标(OLTP vs. OLAP)
 吞吐量
 延迟(或响应时间)
• 低延迟不一定意味着高吞吐量
从山西到广州运煤,一列火车100小时(包括往返)可以运输
10000t 煤,而一架飞机20小时(包括往返)可以运输100t煤。
• 并发度 = 吞吐量 * 延迟
比如一个系统处理某种任务的延迟为1ms,吞吐量为 1000tps,
那么并发度就为1/1000 * 1000 = 1,即单线程模型。
5
一些相关原理
• 80/20原则
• 木桶原理
系统最终性能取决于系统中性能最差的组件,应该关注性能最
差的组件。
• Amdahl定律
定义了串行化系统并行化后的加速比公式(加速比越大,系统
并行化优化效果越好):
加速比 = 优化前系统耗时 / 优化后系统耗时
假设加速比为Speedup,系统串行化比率(串行执行代码所占比
例)为F,CPU数目为N:
Speedup <= 1 / (F + (1 - F) / N)
即当N一定时,F越小,加速比上限越大。
6
性能优化模式
• 设计模式
• 缓冲
• 缓存
• 池化
• 时空互换
• 并行化
• 协议优化
• …
7
性能优化模式 – 单例模式
• 单例模式
减少频繁创建对象开销、减少内存消耗从而减轻GC压力
8
性能优化模式 – 代理模式1
• 延迟重量级对象创建,加快启动速度
9
性能优化模式 – 代理模式2
• 动态代理模式不同实现性能比较
 ASM方式实现的动态代理函数调用性能最高,但需要
对字节码很熟悉,并且不利于维护
JDK本身动态代理函数调用性能最差,而且不够灵活
JDK本身动态代理对象创建性能最高,因为使用native的
defineClass()方法
Java Assist和CGLib实现的动态代理函数调用性能优于
JDK动态代理,一般推荐用这两种实现动态代理
10
性能优化模式 – 代理模式3
• 动态代理模式的实际应用
 Hibernate使用CGLib动态代理实现,达到延迟加载对象
的属性(延迟访问数据库)目的:HibernateProxy接口
CGLib的net.sf.cglib.proxy.LazyLoader 接口可以方便地用
于实现对象延迟加载
11
性能优化模式 – 享元模式
• 与单例模式作用类似,避免对象重复创建
开销
12
性能优化模式 – Value Object模式
• RMI调用中将多个请求零散信息的请求合并
成只请求一个Value Object
比如请求订单信息场景,将getOrderId、getOrderNum等合
并成getOrder。Order就是Value Object。
13
性能优化模式 – 缓冲1
• 缓冲可以协调上层组件和下层组件的性能差,当上层组件
性能优于下层组件时,可以有效减少上层组件对下层组件
的等待时间
14
性能优化模式 – 缓冲2
• 生产者消费者模式
15
性能优化模式 – 缓冲3
• Java IO中读写文件缓冲,有无缓冲性能差为18倍(积分系
统中同样写一个77MB的文件,无缓冲18s,有缓冲1s)
16
性能优化模式 – 缓冲4
17
性能优化模式 – 缓存
• 本地缓存
• 分布式缓存
 Redis、Memcached
 避免缓存穿透,比如有大量的null请求穿透Cache,则
考虑为null也作Cache
• 程序的时间局部性原理
18
性能优化模式 – 池化
• 如果一个类的实例对象被频繁使用,那么不必每次都生成
新实例,可以将这些类的实例保存在一个池中,可以大大
减轻创建对象和销毁对象开销
 数据库连接池
 线程池
 对象池
19
性能优化模式 – 时空互换1
• 时间换空间
内存资源紧张
实例:不使用第三个变量交换两个变量
20
性能优化模式 – 时空互换2
• 空间换时间
最常见
常用算法:缓存、Hash、查表法 …
实例:计算一个字符串数组中出现次数最多的字符串
21
性能优化模式 – 并行化
• 多进程
• 多线程:
 线程池最佳线程数目 =(线程等待时间与线程CPU时间
之比 + 1)* CPU数目
• 实例 :
 从磁盘串行和并行读取 30 张大小为 256K 的缩略图,
磁盘IO速度为 30 MB/s,磁盘每次寻道耗时 10 ms
22
性能优化模式 – 协议优化
• 各种序列化协议时间和空间对比
23
代码调优 – 字符串 1
• JDK 1.6的substring方法存在内存泄露风险,
JDK 1.7已修复
24
代码调优 – 字符串2
• 字符串分割:优先使用StringTokenizer而不是String
类的split方法
• 在性能敏感代码中优先使用String类的charAt和
indexOf方法
 比如用charAt代替startWith和endWith
• 涉及大量字符串拼接优先使用StringBuffer和
StringBuilder
• 如果能预估字符串长度,最好提供容量参数
25
代码调优 – 数据结构1
• ArrayList和LinkedList的增加元素方法比较
 add(E e):在末尾追加元素,ArrayList未必比LinkedList慢,如果ArrayList指
定了合适的capacity(capcity设置过小会频繁扩容)
 add(int index, E e):在指定位置插入元素,LinkedList性能优势开始凸显
• ArrayList和LinkedList的删除元素方法,毋庸置疑LinkedList性能更
优
• ArrayList和LinkedList的遍历操作
 不推荐使用for-each遍历
 ArrayList推荐用for循环遍历(随机访问)
 LinkedList推荐用迭代器遍历,避免用for循环遍历,速度奇慢
26
代码调优 – 数据结构2
• HashMap和HashSet
 哈希算法是否高效是性能的关键
良好的哈希算法除了函数本身运行性能高效外,还必
须满足尽量均匀地将值分散到哈希地址空间,并且哈
希冲突尽可能少
27
代码调优 – 异常开销
• 异常很方便,开销也很大
 主要是Throwable的构造函数调用了fillInStackTrace()
方法构建异常栈,如果异常层次一深开销就更大了
避免不必要的异常(如异常被用作正常业务流程控
制)
 避免在循环体内使用try-catch
重写fillInStackTrace()方法,提供空实现
28
代码调优 – IO与NIO
• 标准IO包中的类不足以满足高效读写文件的目的,只有
BufferedReader、BufferedWriter、BufferedInputStream、
BuffredOutputStream四个类提供缓冲读写支持
• NIO包极大改善了这个局面,Buffer是NIO的一个核心类
• 如果涉及大文件随机读写,建议使用MappedByteBuffer和
RandomAccessFile
29
代码调优 – 并发编程模式
• 生产者消费者模式(略)
• Future模式
• Master-Worker模式
• 不变模式
• …
30
代码调优 – Future模式
• Future模式的优势:在耗时任务执行的同时可以
去执行其他操作
31
代码调优 – Master-Worker模式
• 包含一个Master线程和多个Worker线程,Master线程接收用户请求、协调
Worker线程并整合最终处理结果。多个Worker线程协作处理用户请求。JDK 7
开始提供了fork/join框架。
32
代码调优 – 不变模式
• 使用不变模式后,不变类的所有实例方法都不需要同步
• JDK中的典型不变类String、Integer、Boolean等
• 不变类对象创建后,其内部状态不再发生变化
• 不变类必须保证下面4条
 去除所有setter方法和所有修改内部状态方法
 所有属性都用private final标记
 确保没有子类可以重载修改它的行为
 有一个可以创建完整对象的构造函数
33
代码调优 – 并发数据结构
• CopyOnWriteArrayList
 读不加锁,写时先获取对象副本,再修改副本最后写回,写会加
锁
 适合读远多于写或者遍历操作数量远多于可变操作数量的场景,
比如监听器列表
• CopyOnWriteSet
• ConcurrentHashMap
• ConcurrentLinkedQueue
 适用于高并发场景下的队列,无锁
• BlockingQueue
• …
34
代码调优 – 锁优化
• 读写锁分离,ReadWriteLock
• 无锁化,ThreadLocal、CopyOnWriteArrayList(读)、ConcurrentLinkedQueue
• 减少锁粒度,ConcurrentHashMap分离锁
• 减少锁持有时间,最小化同步代码块
• 乐观CAS锁,AtomicInteger、AtomicLong、AtomicReference
• 自旋锁,JVM层面锁优化,-XX:+UseSpinning开启自旋锁
 自旋锁使得在线程没有获得锁情况下不被挂起而是转去执行空循环
 线程挂起、恢复开销很大
 适用于访问共享资源时间较短情况
• 锁消除,JVM层面锁优化,-server –XX:+DoEscapeAnalysis –XX:+EliminateLocks
开启
• 偏向锁,JVM层面锁优化,-XX:+UseBiasedLocking
35
代码调优 – 其他小Tip
• 尽量使用JDK中提供的API,比如Arrays.sort、
System.arrayCopy(native方法)
• 对于重量级对象创建可以用clone()代替new
• 静态方法代替实例方法
• 嵌套循环中将忙循环放在内层
• …
36
JVM调优 – JMM
• 程序计数器
• Java虚拟机栈
• 本地方法栈(对应native方法)
• 堆
 分代:新生代(Eden、s0、s1)、老年代
• 方法区
又称永久区或持久代,主要存放常量信息和类信息
Hot Spot虚拟机中方法区也会进行GC
37
JVM调优 – JVM内存分配参数
• 堆内存:-Xmx、-Xms
• 新生代:-Xmn,一般设置为整个堆空间的1/4到1/3
 Hot Spot虚拟机中-XX:NewSize、-XX:MaxNewSize
• 持久代:-XX:PermSize、-XX:MaxPermSize
• 线程栈:-Xss
• 堆比例参数
 -XX:SurvivorRatio = eden / s0 = eden / s1
 -XX:NewRatio = 老年代 / 新生代
38
JVM调优 – GC算法
• Mark-Sweep算法:会导致不连续内存空间
• Copy算法:比Mark-Sweep高效,新生代GC算法
• Mark-Compact算法:基于Mark-Sweep改进的算法,第一阶
段Mark与Mark-Sweep基本相同,但第二阶段压缩存活对象
到内存一端,之后清理边界外的所有其他空间。老年代GC
算法
39
JVM调优 – GC相关参数
• 堆Dump:-XX:-HeapDumpOnOutOfMemoryError -
XX:HeapDumpPath=/var/heapdump
• 获取GC信息:-verbose:gc或-XX:+PrintGC或-
XX:+PrintGCDetails,-XX:PrintHeapAtGC、-
XX:PrintGCApplicationStoppedTime
• 类和对象跟踪:-XX:+TraceClassLoading、-
XX:+TraceClassUnloading
• …
40
JVM调优 – GC友好Tip
• GC分代假设:绝大部分对象的生命周期都很短
• 分配小对象开销很小,不要吝啬去创建小对象
• Young GC速度远高于Full GC,尽量避免对象提升到老年代,
Young GC应该占绝大部分,Full GC应该很少
 让对象生命周期尽可能短,避免生命周期过长被提升到老年代
 为新生代预留足够空间,使大部分对象停留在新生代
 尽量避免短命大对象,使用-XX:PretenureSizeThreshold设置大对象
直接进入老年代的阈值
• 避免堆震荡,设置相同的-Xmx和-Xms,可以减少GC次数
• 不可变对象对GC友好:减少卡表扫描
• …
41
结束
42
参考资料
• 《Java程序性能优化》 葛一鸣
• http://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-
ladis2009.pdf
• http://blog.hesey.net/2014/05/gc-oriented-java-programming.html
• http://www.javaworld.com/article/2078623/core-java/jvm-
performance-optimization--part-1--a-jvm-technology-primer.html
• http://www.javaworld.com/article/2076539/build-ci-sdlc/java-
performance-programming--part-1--smart-object-management-
saves-the-day.html
• http://www.javaworld.com/article/2074893/build-ci-sdlc/design-
for-performance--part-1--interfaces-matter.html
• http://www.ibm.com/developerworks/cn/java/l-javaio/
• …
43

More Related Content

Viewers also liked

数据分析系统架构设计
数据分析系统架构设计数据分析系统架构设计
数据分析系统架构设计学峰 司
 
Web前端性能优化 2014
Web前端性能优化 2014Web前端性能优化 2014
Web前端性能优化 2014Yubei Li
 
Jvm Performance Tunning
Jvm Performance TunningJvm Performance Tunning
Jvm Performance TunningTerry Cho
 
使用 Amazon Pinpoint 讓你的行動 App 更精準接觸客群
使用 Amazon Pinpoint 讓你的行動 App 更精準接觸客群使用 Amazon Pinpoint 讓你的行動 App 更精準接觸客群
使用 Amazon Pinpoint 讓你的行動 App 更精準接觸客群Amazon Web Services
 
MySQL数据库设计、优化
MySQL数据库设计、优化MySQL数据库设计、优化
MySQL数据库设计、优化Jinrong Ye
 
MySQL技术分享:一步到位实现mysql优化
MySQL技术分享:一步到位实现mysql优化MySQL技术分享:一步到位实现mysql优化
MySQL技术分享:一步到位实现mysql优化Jinrong Ye
 

Viewers also liked (6)

数据分析系统架构设计
数据分析系统架构设计数据分析系统架构设计
数据分析系统架构设计
 
Web前端性能优化 2014
Web前端性能优化 2014Web前端性能优化 2014
Web前端性能优化 2014
 
Jvm Performance Tunning
Jvm Performance TunningJvm Performance Tunning
Jvm Performance Tunning
 
使用 Amazon Pinpoint 讓你的行動 App 更精準接觸客群
使用 Amazon Pinpoint 讓你的行動 App 更精準接觸客群使用 Amazon Pinpoint 讓你的行動 App 更精準接觸客群
使用 Amazon Pinpoint 讓你的行動 App 更精準接觸客群
 
MySQL数据库设计、优化
MySQL数据库设计、优化MySQL数据库设计、优化
MySQL数据库设计、优化
 
MySQL技术分享:一步到位实现mysql优化
MySQL技术分享:一步到位实现mysql优化MySQL技术分享:一步到位实现mysql优化
MySQL技术分享:一步到位实现mysql优化
 

Similar to Java性能调优浅谈

Notes of jcip
Notes of jcipNotes of jcip
Notes of jcipDai Jun
 
Serverless Event Streaming with Pulsar Functions-xiaolong
Serverless Event Streaming with Pulsar Functions-xiaolongServerless Event Streaming with Pulsar Functions-xiaolong
Serverless Event Streaming with Pulsar Functions-xiaolongStreamNative
 
淘宝前端优化
淘宝前端优化淘宝前端优化
淘宝前端优化锐 张
 
淘宝前台系统优化实践“吞吐量优化”-Qcon2011
淘宝前台系统优化实践“吞吐量优化”-Qcon2011淘宝前台系统优化实践“吞吐量优化”-Qcon2011
淘宝前台系统优化实践“吞吐量优化”-Qcon2011Yiwei Ma
 
第三届阿里中间件性能挑战赛季军答辩ppt - rapids团队
第三届阿里中间件性能挑战赛季军答辩ppt - rapids团队第三届阿里中间件性能挑战赛季军答辩ppt - rapids团队
第三届阿里中间件性能挑战赛季军答辩ppt - rapids团队煜林 车
 
服务器基准测试-叶金荣@CYOU-20121130
服务器基准测试-叶金荣@CYOU-20121130服务器基准测试-叶金荣@CYOU-20121130
服务器基准测试-叶金荣@CYOU-20121130Jinrong Ye
 
[圣思园][Java SE]Io 3
[圣思园][Java SE]Io 3[圣思园][Java SE]Io 3
[圣思园][Java SE]Io 3ArBing Xie
 
罗立刚 高性能模糊查询内存数据库Ems
罗立刚 高性能模糊查询内存数据库Ems罗立刚 高性能模糊查询内存数据库Ems
罗立刚 高性能模糊查询内存数据库Emsgettyying
 
MySQL压力测试经验
MySQL压力测试经验MySQL压力测试经验
MySQL压力测试经验Jinrong Ye
 
Ecmascript
EcmascriptEcmascript
Ecmascriptjay li
 
纵览Loadrunner核心功能
纵览Loadrunner核心功能纵览Loadrunner核心功能
纵览Loadrunner核心功能beiyu95
 
分布式存储与TDDL
分布式存储与TDDL分布式存储与TDDL
分布式存储与TDDLmysqlops
 
04.web sphere培训 应用websphere优化
04.web sphere培训 应用websphere优化04.web sphere培训 应用websphere优化
04.web sphere培训 应用websphere优化littlecong
 
诗檀软件 Oracle开发优化基础
诗檀软件 Oracle开发优化基础 诗檀软件 Oracle开发优化基础
诗檀软件 Oracle开发优化基础 maclean liu
 
20110625.【打造高效能的cdn系统】.易统
20110625.【打造高效能的cdn系统】.易统20110625.【打造高效能的cdn系统】.易统
20110625.【打造高效能的cdn系统】.易统锐 张
 
Sql语句编写优化和基本原理总结
Sql语句编写优化和基本原理总结Sql语句编写优化和基本原理总结
Sql语句编写优化和基本原理总结wangchongan
 
Java应用性能测试与分析
Java应用性能测试与分析Java应用性能测试与分析
Java应用性能测试与分析Frank Lee
 
MySQL运维那些事
MySQL运维那些事 MySQL运维那些事
MySQL运维那些事 Leo Zhou
 

Similar to Java性能调优浅谈 (20)

Multithread
MultithreadMultithread
Multithread
 
Notes of jcip
Notes of jcipNotes of jcip
Notes of jcip
 
Elasticsearch 簡介
Elasticsearch 簡介Elasticsearch 簡介
Elasticsearch 簡介
 
Serverless Event Streaming with Pulsar Functions-xiaolong
Serverless Event Streaming with Pulsar Functions-xiaolongServerless Event Streaming with Pulsar Functions-xiaolong
Serverless Event Streaming with Pulsar Functions-xiaolong
 
淘宝前端优化
淘宝前端优化淘宝前端优化
淘宝前端优化
 
淘宝前台系统优化实践“吞吐量优化”-Qcon2011
淘宝前台系统优化实践“吞吐量优化”-Qcon2011淘宝前台系统优化实践“吞吐量优化”-Qcon2011
淘宝前台系统优化实践“吞吐量优化”-Qcon2011
 
第三届阿里中间件性能挑战赛季军答辩ppt - rapids团队
第三届阿里中间件性能挑战赛季军答辩ppt - rapids团队第三届阿里中间件性能挑战赛季军答辩ppt - rapids团队
第三届阿里中间件性能挑战赛季军答辩ppt - rapids团队
 
服务器基准测试-叶金荣@CYOU-20121130
服务器基准测试-叶金荣@CYOU-20121130服务器基准测试-叶金荣@CYOU-20121130
服务器基准测试-叶金荣@CYOU-20121130
 
[圣思园][Java SE]Io 3
[圣思园][Java SE]Io 3[圣思园][Java SE]Io 3
[圣思园][Java SE]Io 3
 
罗立刚 高性能模糊查询内存数据库Ems
罗立刚 高性能模糊查询内存数据库Ems罗立刚 高性能模糊查询内存数据库Ems
罗立刚 高性能模糊查询内存数据库Ems
 
MySQL压力测试经验
MySQL压力测试经验MySQL压力测试经验
MySQL压力测试经验
 
Ecmascript
EcmascriptEcmascript
Ecmascript
 
纵览Loadrunner核心功能
纵览Loadrunner核心功能纵览Loadrunner核心功能
纵览Loadrunner核心功能
 
分布式存储与TDDL
分布式存储与TDDL分布式存储与TDDL
分布式存储与TDDL
 
04.web sphere培训 应用websphere优化
04.web sphere培训 应用websphere优化04.web sphere培训 应用websphere优化
04.web sphere培训 应用websphere优化
 
诗檀软件 Oracle开发优化基础
诗檀软件 Oracle开发优化基础 诗檀软件 Oracle开发优化基础
诗檀软件 Oracle开发优化基础
 
20110625.【打造高效能的cdn系统】.易统
20110625.【打造高效能的cdn系统】.易统20110625.【打造高效能的cdn系统】.易统
20110625.【打造高效能的cdn系统】.易统
 
Sql语句编写优化和基本原理总结
Sql语句编写优化和基本原理总结Sql语句编写优化和基本原理总结
Sql语句编写优化和基本原理总结
 
Java应用性能测试与分析
Java应用性能测试与分析Java应用性能测试与分析
Java应用性能测试与分析
 
MySQL运维那些事
MySQL运维那些事 MySQL运维那些事
MySQL运维那些事
 

Java性能调优浅谈

  • 2. 提纲 • 一些相关原理 • 性能测量指标 • 性能优化模式 • 代码调优 • JVM调优 • … 2
  • 3. 性能测量指标 - 1 • 各类资源消耗情况:  磁盘IO  内存占用  CPU  数据库  网络  锁竞争  … 3
  • 5. 性能测量指标 - 3 • 其他最常用的两个指标(OLTP vs. OLAP)  吞吐量  延迟(或响应时间) • 低延迟不一定意味着高吞吐量 从山西到广州运煤,一列火车100小时(包括往返)可以运输 10000t 煤,而一架飞机20小时(包括往返)可以运输100t煤。 • 并发度 = 吞吐量 * 延迟 比如一个系统处理某种任务的延迟为1ms,吞吐量为 1000tps, 那么并发度就为1/1000 * 1000 = 1,即单线程模型。 5
  • 6. 一些相关原理 • 80/20原则 • 木桶原理 系统最终性能取决于系统中性能最差的组件,应该关注性能最 差的组件。 • Amdahl定律 定义了串行化系统并行化后的加速比公式(加速比越大,系统 并行化优化效果越好): 加速比 = 优化前系统耗时 / 优化后系统耗时 假设加速比为Speedup,系统串行化比率(串行执行代码所占比 例)为F,CPU数目为N: Speedup <= 1 / (F + (1 - F) / N) 即当N一定时,F越小,加速比上限越大。 6
  • 7. 性能优化模式 • 设计模式 • 缓冲 • 缓存 • 池化 • 时空互换 • 并行化 • 协议优化 • … 7
  • 8. 性能优化模式 – 单例模式 • 单例模式 减少频繁创建对象开销、减少内存消耗从而减轻GC压力 8
  • 9. 性能优化模式 – 代理模式1 • 延迟重量级对象创建,加快启动速度 9
  • 10. 性能优化模式 – 代理模式2 • 动态代理模式不同实现性能比较  ASM方式实现的动态代理函数调用性能最高,但需要 对字节码很熟悉,并且不利于维护 JDK本身动态代理函数调用性能最差,而且不够灵活 JDK本身动态代理对象创建性能最高,因为使用native的 defineClass()方法 Java Assist和CGLib实现的动态代理函数调用性能优于 JDK动态代理,一般推荐用这两种实现动态代理 10
  • 11. 性能优化模式 – 代理模式3 • 动态代理模式的实际应用  Hibernate使用CGLib动态代理实现,达到延迟加载对象 的属性(延迟访问数据库)目的:HibernateProxy接口 CGLib的net.sf.cglib.proxy.LazyLoader 接口可以方便地用 于实现对象延迟加载 11
  • 12. 性能优化模式 – 享元模式 • 与单例模式作用类似,避免对象重复创建 开销 12
  • 13. 性能优化模式 – Value Object模式 • RMI调用中将多个请求零散信息的请求合并 成只请求一个Value Object 比如请求订单信息场景,将getOrderId、getOrderNum等合 并成getOrder。Order就是Value Object。 13
  • 14. 性能优化模式 – 缓冲1 • 缓冲可以协调上层组件和下层组件的性能差,当上层组件 性能优于下层组件时,可以有效减少上层组件对下层组件 的等待时间 14
  • 15. 性能优化模式 – 缓冲2 • 生产者消费者模式 15
  • 16. 性能优化模式 – 缓冲3 • Java IO中读写文件缓冲,有无缓冲性能差为18倍(积分系 统中同样写一个77MB的文件,无缓冲18s,有缓冲1s) 16
  • 18. 性能优化模式 – 缓存 • 本地缓存 • 分布式缓存  Redis、Memcached  避免缓存穿透,比如有大量的null请求穿透Cache,则 考虑为null也作Cache • 程序的时间局部性原理 18
  • 19. 性能优化模式 – 池化 • 如果一个类的实例对象被频繁使用,那么不必每次都生成 新实例,可以将这些类的实例保存在一个池中,可以大大 减轻创建对象和销毁对象开销  数据库连接池  线程池  对象池 19
  • 20. 性能优化模式 – 时空互换1 • 时间换空间 内存资源紧张 实例:不使用第三个变量交换两个变量 20
  • 21. 性能优化模式 – 时空互换2 • 空间换时间 最常见 常用算法:缓存、Hash、查表法 … 实例:计算一个字符串数组中出现次数最多的字符串 21
  • 22. 性能优化模式 – 并行化 • 多进程 • 多线程:  线程池最佳线程数目 =(线程等待时间与线程CPU时间 之比 + 1)* CPU数目 • 实例 :  从磁盘串行和并行读取 30 张大小为 256K 的缩略图, 磁盘IO速度为 30 MB/s,磁盘每次寻道耗时 10 ms 22
  • 23. 性能优化模式 – 协议优化 • 各种序列化协议时间和空间对比 23
  • 24. 代码调优 – 字符串 1 • JDK 1.6的substring方法存在内存泄露风险, JDK 1.7已修复 24
  • 25. 代码调优 – 字符串2 • 字符串分割:优先使用StringTokenizer而不是String 类的split方法 • 在性能敏感代码中优先使用String类的charAt和 indexOf方法  比如用charAt代替startWith和endWith • 涉及大量字符串拼接优先使用StringBuffer和 StringBuilder • 如果能预估字符串长度,最好提供容量参数 25
  • 26. 代码调优 – 数据结构1 • ArrayList和LinkedList的增加元素方法比较  add(E e):在末尾追加元素,ArrayList未必比LinkedList慢,如果ArrayList指 定了合适的capacity(capcity设置过小会频繁扩容)  add(int index, E e):在指定位置插入元素,LinkedList性能优势开始凸显 • ArrayList和LinkedList的删除元素方法,毋庸置疑LinkedList性能更 优 • ArrayList和LinkedList的遍历操作  不推荐使用for-each遍历  ArrayList推荐用for循环遍历(随机访问)  LinkedList推荐用迭代器遍历,避免用for循环遍历,速度奇慢 26
  • 27. 代码调优 – 数据结构2 • HashMap和HashSet  哈希算法是否高效是性能的关键 良好的哈希算法除了函数本身运行性能高效外,还必 须满足尽量均匀地将值分散到哈希地址空间,并且哈 希冲突尽可能少 27
  • 28. 代码调优 – 异常开销 • 异常很方便,开销也很大  主要是Throwable的构造函数调用了fillInStackTrace() 方法构建异常栈,如果异常层次一深开销就更大了 避免不必要的异常(如异常被用作正常业务流程控 制)  避免在循环体内使用try-catch 重写fillInStackTrace()方法,提供空实现 28
  • 29. 代码调优 – IO与NIO • 标准IO包中的类不足以满足高效读写文件的目的,只有 BufferedReader、BufferedWriter、BufferedInputStream、 BuffredOutputStream四个类提供缓冲读写支持 • NIO包极大改善了这个局面,Buffer是NIO的一个核心类 • 如果涉及大文件随机读写,建议使用MappedByteBuffer和 RandomAccessFile 29
  • 30. 代码调优 – 并发编程模式 • 生产者消费者模式(略) • Future模式 • Master-Worker模式 • 不变模式 • … 30
  • 31. 代码调优 – Future模式 • Future模式的优势:在耗时任务执行的同时可以 去执行其他操作 31
  • 32. 代码调优 – Master-Worker模式 • 包含一个Master线程和多个Worker线程,Master线程接收用户请求、协调 Worker线程并整合最终处理结果。多个Worker线程协作处理用户请求。JDK 7 开始提供了fork/join框架。 32
  • 33. 代码调优 – 不变模式 • 使用不变模式后,不变类的所有实例方法都不需要同步 • JDK中的典型不变类String、Integer、Boolean等 • 不变类对象创建后,其内部状态不再发生变化 • 不变类必须保证下面4条  去除所有setter方法和所有修改内部状态方法  所有属性都用private final标记  确保没有子类可以重载修改它的行为  有一个可以创建完整对象的构造函数 33
  • 34. 代码调优 – 并发数据结构 • CopyOnWriteArrayList  读不加锁,写时先获取对象副本,再修改副本最后写回,写会加 锁  适合读远多于写或者遍历操作数量远多于可变操作数量的场景, 比如监听器列表 • CopyOnWriteSet • ConcurrentHashMap • ConcurrentLinkedQueue  适用于高并发场景下的队列,无锁 • BlockingQueue • … 34
  • 35. 代码调优 – 锁优化 • 读写锁分离,ReadWriteLock • 无锁化,ThreadLocal、CopyOnWriteArrayList(读)、ConcurrentLinkedQueue • 减少锁粒度,ConcurrentHashMap分离锁 • 减少锁持有时间,最小化同步代码块 • 乐观CAS锁,AtomicInteger、AtomicLong、AtomicReference • 自旋锁,JVM层面锁优化,-XX:+UseSpinning开启自旋锁  自旋锁使得在线程没有获得锁情况下不被挂起而是转去执行空循环  线程挂起、恢复开销很大  适用于访问共享资源时间较短情况 • 锁消除,JVM层面锁优化,-server –XX:+DoEscapeAnalysis –XX:+EliminateLocks 开启 • 偏向锁,JVM层面锁优化,-XX:+UseBiasedLocking 35
  • 36. 代码调优 – 其他小Tip • 尽量使用JDK中提供的API,比如Arrays.sort、 System.arrayCopy(native方法) • 对于重量级对象创建可以用clone()代替new • 静态方法代替实例方法 • 嵌套循环中将忙循环放在内层 • … 36
  • 37. JVM调优 – JMM • 程序计数器 • Java虚拟机栈 • 本地方法栈(对应native方法) • 堆  分代:新生代(Eden、s0、s1)、老年代 • 方法区 又称永久区或持久代,主要存放常量信息和类信息 Hot Spot虚拟机中方法区也会进行GC 37
  • 38. JVM调优 – JVM内存分配参数 • 堆内存:-Xmx、-Xms • 新生代:-Xmn,一般设置为整个堆空间的1/4到1/3  Hot Spot虚拟机中-XX:NewSize、-XX:MaxNewSize • 持久代:-XX:PermSize、-XX:MaxPermSize • 线程栈:-Xss • 堆比例参数  -XX:SurvivorRatio = eden / s0 = eden / s1  -XX:NewRatio = 老年代 / 新生代 38
  • 39. JVM调优 – GC算法 • Mark-Sweep算法:会导致不连续内存空间 • Copy算法:比Mark-Sweep高效,新生代GC算法 • Mark-Compact算法:基于Mark-Sweep改进的算法,第一阶 段Mark与Mark-Sweep基本相同,但第二阶段压缩存活对象 到内存一端,之后清理边界外的所有其他空间。老年代GC 算法 39
  • 40. JVM调优 – GC相关参数 • 堆Dump:-XX:-HeapDumpOnOutOfMemoryError - XX:HeapDumpPath=/var/heapdump • 获取GC信息:-verbose:gc或-XX:+PrintGC或- XX:+PrintGCDetails,-XX:PrintHeapAtGC、- XX:PrintGCApplicationStoppedTime • 类和对象跟踪:-XX:+TraceClassLoading、- XX:+TraceClassUnloading • … 40
  • 41. JVM调优 – GC友好Tip • GC分代假设:绝大部分对象的生命周期都很短 • 分配小对象开销很小,不要吝啬去创建小对象 • Young GC速度远高于Full GC,尽量避免对象提升到老年代, Young GC应该占绝大部分,Full GC应该很少  让对象生命周期尽可能短,避免生命周期过长被提升到老年代  为新生代预留足够空间,使大部分对象停留在新生代  尽量避免短命大对象,使用-XX:PretenureSizeThreshold设置大对象 直接进入老年代的阈值 • 避免堆震荡,设置相同的-Xmx和-Xms,可以减少GC次数 • 不可变对象对GC友好:减少卡表扫描 • … 41
  • 43. 参考资料 • 《Java程序性能优化》 葛一鸣 • http://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote- ladis2009.pdf • http://blog.hesey.net/2014/05/gc-oriented-java-programming.html • http://www.javaworld.com/article/2078623/core-java/jvm- performance-optimization--part-1--a-jvm-technology-primer.html • http://www.javaworld.com/article/2076539/build-ci-sdlc/java- performance-programming--part-1--smart-object-management- saves-the-day.html • http://www.javaworld.com/article/2074893/build-ci-sdlc/design- for-performance--part-1--interfaces-matter.html • http://www.ibm.com/developerworks/cn/java/l-javaio/ • … 43

Editor's Notes

  1. 吞吐量:相当一段时间内测量出来的系统单位时间处理的任务数或事务数(TPS) 延迟: 一般包括单向延迟(One-way Latency)和往返延迟(Round Trip Latency),实际测量时一般取往返延迟。     它的单位一般是ms、s、min等。