问题背景:系统启动后,啥事没干,不停的YGC,并且YGC能回收彻底。
排查流程:
(1)top + shift jstack 输出 、jmap 输出、 没发现异常
(2)线程数量非常多,关闭cache、关闭查询统计输出,依然出现ygc
(3)怀疑reader reopen没有关闭、资源泄露,输出reader计数,没有发现异常
(4)调整jvm参数,依然没有效果
(5)代码步步打开,最后发现无意发现问题,原来实时add 操作也有统计输出,关掉这部分,ygc解决。
最终定位原因:
线程生成了大量 new String 对象了。String对象内存杀手!!!!慎用!lucene4.0 去string对象,无疑是非常大的好处。面向byte 层的cache、byte的term!!!
代码如下,逻辑功能:等间隔输出统计信息。
public class PerfTracer {
private AtomicInteger counter;
private long startTime;
private long intervalTime = 1 * 60 * 1000;
private Log logger;
private String name;
public PerfTracer(String name,Log logger) {
this.logger = logger;
this.name = name;
this.startTime = System.currentTimeMillis();
this.counter = new AtomicInteger(0);
}
public void increment() {
counter.incrementAndGet();
if((System.currentTimeMillis() - startTime) >= intervalTime){
this.onTime();
}
}
public void reset() {
counter.set(0);
this.startTime = System.currentTimeMillis();
}
protected String exportLog() {
return "[" + name+"-statistics] " + (counter.get() / (intervalTime/1000)) + "-tps";
}
protected void onTime() {
logger.warn(this.exportLog());
this.reset();
}
}
调用
....// 其他代码
perfTracer = new PerfTracer("DefaultRealTimeService-Write-CommitLog", log) {
protected void onTime() {
log.warn(this.exportLog());
log.warn(getStatistics());
this.reset();
}
};
Thread printThread = new Thread(new PrintLogTask(perfTracer));
printThread.start();
...// 其他代码
public String getStatistics() {
StringBuilder sb = new StringBuilder();
sb.append("CoreName:{").append(coreName).append("} ");
sb.append("1000ms: {").append(below1000.get()).append("}").append(" ");
sb.append("1000ms~2000ms: {").append(below2000.get()).append("}").append(" ");
sb.append("2000ms~5000ms: {").append(below5000.get()).append("}").append(" ");
sb.append("5000ms++: {").append(above5000.get()).append("}").append(" ");
return sb.toString();
}