我创建了一个类的数组,该类的长度很长,大约有150M个元素,按键排序(描述如下)。然后,我构建了一个简单的http服务器,以将每个请求作为二进制搜索功能反馈给阵列。(我确定服务器的工作正常)
数据初始化就很好(因为速度很慢)。二进制搜索功能达到预期的速度。
问题是:响应只是快速的一段时间(10分钟,1个小时……多种时间范围),然后服务器花费相当长的时间(几分钟)来为请求执行二进制搜索功能,然后快速返回,然后过一会儿...虽然很慢,但我检查服务器状态(htop),看来jvm在GC中。
当我将大数组拆分为较小的数组时,不会发生此问题,例如:15个元素的10个数组,在搜索之前找到了目标数组。所以我想当我创建太大的数组时,JVM中会发生一些事情
(编辑:我将大数组拆分成碎片没有问题,因为我将“ SiteInfo”对象实现为本地对象,JVM中的大量对象减少了。因此,由我创建的对象过多导致的问题如下,谢谢)
伙计们,您对我的问题有任何想法吗?
(我发布了我的代码,有一些我认为并不重要的伪代码)
public static class Token2TopSite implements Comparable<Token2TopSite> {
public final String token; // this is key for binary search
public final SiteInfo[] topSites; // just data, not important at this question, I think
public Token2TopSite(String token, SiteInfo[] topSites) {
this.token = token;
this.topSites = topSites;
}
@Override
public int compareTo(Token2TopSite o) {
return token.compareTo(o.token);
}
public static void main(String[] args) {
Token2TopSite[] array = new Token2TopSite[150 * 1000000];
...; // init data for array, this runs properly
Arrays.sort(array);
startServerOnArray(array); // each request is a element search on the array
}
}
我认为Omry Yadan的诊断可能是正确的。这些听起来像GC暂停,如果堆中有大量的长期可访问对象,则它们可能特别糟糕。执行“完整”收集时,GC必须遍历所有活动对象。
(您可以通过启用GC日志记录并将服务器性能较慢的时间与GC事件进行比较来确认这确实是与GC相关的问题。)
但是,我不同意他建议的解决方案。
与重写应用程序不同,更简单的解决方案是将JVM配置为使用“并发”或“低暂停”垃圾收集器。只需在启动Web服务器JVM的命令上设置一些参数即可。
以下是一些Oracle参考:
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句