垃圾回收微调与其它的性能微调活动没有什么区别。
不屈服于对应用程序的随机部分进行调整,你需要确保你理解当前的情况和期望的结果。
通常按照以下过程来处理容易些。
1.声明你的性能目标
2.运行测试
3.测量
4.和目标进行比较
5.改变并回归测试
设定与性能微调相关的目标和可测量的三维是很重要的。这些目标包括延迟,吞吐量和容量,为了更好的理解我推荐大家看一下 垃圾回收手册 中对应的章节。
我们看看怎样在实践中设置和达成目标。出于这个目的,我们看一下一个示例代码。
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Producer implements Runnable {
private static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
private Deque<byte[]> deque;
private int objectSize;
private int queueSize;
public Producer(int objectSize, int ttl) {
this.deque = new ArrayDeque<byte[]>();
this.objectSize = objectSize;
this.queueSize = ttl * 1000;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
deque.add(new byte[objectSize]);
if (deque.size() > queueSize) {
deque.poll();
}
}
}
public static void main(String[] args) throws InterruptedException {
executorService.scheduleAtFixedRate(new Producer(200 * 1024 * 1024 / 1000, 5), 0, 100, TimeUnit.MILLISECONDS);
executorService.scheduleAtFixedRate(new Producer(50 * 1024 * 1024 / 1000, 120), 0, 100, TimeUnit.MILLISECONDS);
TimeUnit.MINUTES.sleep(10);
executorService.shutdownNow();
}
}
这段代码每100毫秒提交两个任务。每个任务模拟指定生命周期的对象:创建对象,在预定时间内让他们离开并且忘掉他们,允许GC回收内存。
当运行示例代码时打开GC日志记录,参数如下:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps
我们开始看到上述参数对垃圾回收日志的影响,类似下面的输出:
2015-06-04T13:34:16.119-0200: 1.723: [GC (Allocation Failure) [PSYoungGen: 114016K->73191K(234496K)] 421540K->421269K(745984K), 0.0858176 secs] [Times: user=0.04 sys=0.06, real=0.09 secs]
2015-06-04T13:34:16.738-0200: 2.342: [GC (Allocation Failure) [PSYoungGen: 234462K->93677K(254976K)] 582540K->593275K(766464K), 0.2357086 secs] [Times: user=0.11 sys=0.14, real=0.24 secs]
2015-06-04T13:34:16.974-0200: 2.578: [Full GC (Ergonomics) [PSYoungGen: 93677K->70109K(254976K)] [ParOldGen: 499597K->511230K(761856K)] 593275K->581339K(1016832K), [Metaspace: 2936K->2936K(1056768K)], 0.0713174 secs] [Times: user=0.21 sys=0.02, real=0.07 secs]
基于日志信息我们能在头脑中开始改进三种不同目标的情况。
1.确保最糟糕的情况GC暂停不超过一个预定值。
2.确保被停止的应用程序线程的总时间不超过一个预定值。
3.当确保我们能完成合理的延迟或者吞吐量目标时,减少基础消耗。
为了实现这个,上述代码用三种不同的配置运行10分钟导致三种
不同的结果,总结在下表中:
用不同的垃圾回收算法和不同的堆大小运行的试验来测量关于延迟和吞吐量的垃圾回收暂停的持续时间。
试验的细节和结果的解释都在我们的 垃圾回收手册 中。看一下手册中的例子,简单的配置改变是怎样把例子中关于延迟,吞吐量和容量变得完全不同的。
另外,我们了保持例子尽可能的简单,只是改变了限定数量的输入参数,例如试验并没有在不同数量的核心或者不同的堆布局下进行测试。
原文地址:http://blog.csdn.net/supercrsky/article/details/46519887