我创建了一个具有大长度,~150M元素的类的数组,按键排序(描述如下)。然后我构建一个简单的http服务器来反馈每个请求作为数组上的二进制搜索功能。 (我确定服务器的工作正常)
数据启动很好(很慢)。二进制搜索功能如预期的那样快。
问题是:响应只是快一段时间(10分钟,1小时......很多种时间范围),然后服务器花了很长时间(几分钟)为请求做二进制搜索功能,然后它& #39;快退,然后慢一会儿...... 虽然它很慢,但我检查服务器状态(htop),似乎jvm在GC中。
当我将大数组分成较小的数组时,问题不会发生,例如:10个15M元素的数组,我在搜索之前找到了目标数组。所以我想当我创建太大的数组
时,JVM会发生一些事情(编辑:我把大数组分成碎片没有问题,因为我实现了#34; SiteInfo"对象是原生的,JVM中的大量对象减少了。所以问题引起了太多的对象我作为回复而创建,谢谢你们)
伙计们,你对我的问题有任何想法吗?
(我发布了我的代码,其中有一些Pseudocode,我认为它并不重要)
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
}
}
答案 0 :(得分:4)
我认为Omry Yadan的诊断可能是正确的。这听起来像GC暂停,如果你在堆中有大量长期可达的对象,它们可能会特别糟糕。 GC执行&#34;完全&#34;时,GC必须遍历所有活动对象。集合。
(您可以通过启用GC日志记录,并将服务器性能较慢的时间与GC事件进行比较来确认这是确实与GC相关的问题。)
但是,我不同意他建议的解决方案。
更简单的解决方案是将JVM配置为使用&#34;并发&#34;而不是重写应用程序。或者&#34;低暂停&#34;垃圾收集器。只需在命令上设置一些参数即可启动Web服务器的JVM。
以下是一些Oracle参考资料:
答案 1 :(得分:1)
当有超过10万个对象时,JVM无法正常工作。 原因是垃圾收集器在寻找空闲内存时需要遍历所有对象,如果找不到任何可用内容的话。 一种解决方案是使用更少的对象。 我写了一个名为Banana的原始集合库,它实现了自己的内存管理。 它基本上创建了一个(或几个)int数组(int []),并允许您在其上构建动态数据结构(已经实现了几个,HashTable,LinkedList,LRUCache等)。