编程语言
首页 > 编程语言> > java-巨大的LinkedList导致GC开销限制,还有其他解决方案吗?

java-巨大的LinkedList导致GC开销限制,还有其他解决方案吗?

作者:互联网

这是我的代码:

 public void mapTrace(String Path) throws FileNotFoundException, IOException {
    FileReader arq = new FileReader(new File(Path));
    BufferedReader leitor = new BufferedReader(arq, 41943040);
    Integer page;
    String std;
    Integer position = 0;

    while ((std = leitor.readLine()) != null) {
        position++;
        page = Integer.parseInt(std, 16);
        LinkedList<Integer> values = map.get(page);
        if (values == null) {
            values = new LinkedList<>();
            map.put(page, values);
        }
        values.add(position);
    }

    for (LinkedList<Integer> referenceList : map.values()) { 
        Collections.reverse(referenceList); 
    }

}

这是HashMap结构

       Map<Integer, LinkedList<Integer>> map = new HashMap<>();

对于50mb-100mb的跟踪文件,我没有任何问题,但是对于较大的文件,我有:

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: GC overhead limit exceeded

我不知道反向方法是否增加了内存使用,LinkedList是否比其他List结构使用更多的空间,或者我将列表添加到地图的方式是否占用了更多的空间.谁能告诉我什么在占用这么多空间?

解决方法:

Does anyone can tell me what’s using so much space?

简短的答案是使用空间可能是您选择的数据结构的空间开销.

>据我估计,LinkedList< Integer>在64位JVM上,列表中的每个整数大约使用48个字节的存储空间,包括整数本身.
>据我估计,是Map <?,?>.在64位计算机上,每个条目将使用48个字节的存储空间,但不包括表示键和值对象的空间.
现在,您对跟踪大小的估计对于我来说太模糊了,无法插入数字,但是我希望一个1.5Gb跟踪文件需要大量超过2Gb的堆.

给定您提供的数字,合理的经验法则是,使用当前使用的数据结构,跟踪文件将在堆内存中占据其文件大小的大约10倍…

您不想将JVM配置为尝试使用比可用物理RAM更多的内存.否则,您可能会将计算机推入颠簸中……并且操作系统可能会开始终止进程​​.因此,对于8Gb机器,我不建议使用-Xmx8g.

结合使用8Gb机器,您应该能够处理600Mb跟踪文件(假设我的估计是正确的),但是1.5Gb跟踪文件是不可行的.如果您真的需要处理那么大的跟踪文件,我的建议是:

>为您的特定用例设计和实现自定义集合类型,以更有效地利用内存,
>重新考虑算法,以便您无需将整个跟踪文件保存在内存中,或者
>获得更大的机器.

I did some tests before reading your comment, i put -Xmx14g and processed the 600mb file, it took some minutes(about 10) but it did fine.

-Xmx14g选项设置最大堆大小.基于观察到的行为,我希望JVM不需要那么多的内存……也不需要操作系统发出请求.而且,如果您在任务管理器中查看了内存使用情况,那么我希望您看到的数字与此一致.

Then i put -Xmx18g and tried to process the 1,5gb file, and its been running for about 20 minutes. My memory in the task manager is going from 7,80 to 7,90. I wonder if this will finish, how could i use MORE memory than i have? Does it use the HD as virtual memory?

是的,它就是这样做的.

是的,您进程虚拟地址空间的每一页都对应于硬盘上的一页.

如果您的虚拟页面多于物理内存页面,那么在任何给定时间,这些虚拟内存页面中的某些页面将仅驻留在磁盘上.当您的应用程序尝试使用这些非驻留页面之一时,VM硬件会生成一个中断,并且操作系统会找到未使用的页面,并从光盘副本中填充该页面,然后将控制权交还给您的程序.但是,如果您的应用程序很忙,那么它将不得不通过逐出另一个页面来创建该物理内存页面.这可能涉及将逐出页面的内容写入光盘.

最终结果是,当您尝试使用的虚拟地址页远远多于物理内存时,应用程序会生成大量中断,从而导致大量磁盘读写操作.这被称为颠簸.如果您的系统崩溃太严重,系统将花费大部分时间等待光盘读写完成,并且性能会急剧下降.在某些操作系统上,操作系统将尝试通过终止进程来“修复”问题.

标签:hashmap,memory,linked-list,java
来源: https://codeday.me/bug/20191127/2076431.html