文件读取:内存不足错误



我需要浏览大约 3000 个文件夹,每个文件夹包含 300 个 CSV 文件。

这是在((nextLine=csvReader.readNext()) != null)时在行上发生的错误:

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
    at au.com.bytecode.opencsv.CSVParser.parseLine(CSVParser.java:206)
    at au.com.bytecode.opencsv.CSVParser.parseLineMulti(CSVParser.java:174)
    at au.com.bytecode.opencsv.CSVReader.readNext(CSVReader.java:237)
    at DA.readTelemetryData(DA.java:78)
    at DA.main(DA.java:24)

问题是如何解决这个问题?为什么会发生这种情况,我的代码中出了什么问题?

在这里我提供代码:

private static HashMap<Integer,HashMap<Integer,List<double[]>>> readTelemetryData() throws Exception
    {
        HashMap<Integer,HashMap<Integer,List<double[]>>> xy_total = new HashMap<Integer,HashMap<Integer,List<double[]>>>(); 
        for (int i=0; i<Constants.MAX_FOLDERS; i++)
        {
            HashMap<Integer,List<double[]>> xy_total_per_folder= new HashMap<Integer,List<double[]>>();
            for (int j=0; j<Constants.MAX_FILES_INSIDE_FOLDER; j++)
            {               
                CSVReader csvReader = null;
                File f = new File("data/"+ (i+1) +"/"+ (j+1) +".csv");
                if(f.exists())
                {
                    csvReader = new CSVReader(new FileReader(f));
                    List<double[]> xyArr = new ArrayList<double[]>();
                    String[] firstLine=csvReader.readNext();
                    if (firstLine != null) 
                    {
                      String[] nextLine=null;
                      while ((nextLine=csvReader.readNext()) != null) 
                      {
                          double[] d = new double[2];
                          d[0]=Double.parseDouble(nextLine[0]);
                          d[1]=Double.parseDouble(nextLine[1]);
                          xyArr.add(d);
                      }
                    }
                    xy_total_per_folder.put(j, xyArr);
                    csvReader.close();
                }
            }
            xy_total.put(i, xy_total_per_folder);
        }
        return xy_total;
    }

内存不足。

HashMap<Integer,V>是一个相当糟糕的选择。它需要 16 个字节作为密钥,每个条目可能需要 24 个字节 + 死区。然后,您的double[]需要 32 字节(用于存储 16 字节的有效负载)。在数组列表中,您需要另外 4 个字节作为参考...

例如,每行将花费您 36 个字节的 instad 16。

请考虑使用更紧凑的数据结构。GNU Trove 是一个为基元类型提供大量收藏的库;但不要低估数组的价值...

对于处理大量的基元类型(intdouble等),请远离java.util.集合。相反,花额外的时间来组织你的记忆。

例如,您可以使用 Trove 的 TDoubleArrayList ,一个用于所有 x 值,一个用于所有 y 值,而不是为每行使用一个数组。读取完文件后,可以将它们转换为最小double[] x; double[] y;数组,并重用TDoubleArrayList来分析下一个文件。

最后但并非最不重要的一点是,Java 默认只使用内存的 25%。 使用-Xmx来增加限制。

运行内存探查器。大部分内存分配在哪里?所有这些都需要吗?也许您正在使用的 CSV 浏览器有内存泄漏!使用内存探查器是一种简单的查找方法。

但是要算一算。你有多少行 - 你能把它们全部放进内存里吗

这种行为通常有两个原因:

  1. 内存泄漏。这意味着您编程存储不再需要的数据。分析要修复的内存转储。

  2. 内存不足,因为您的编程实际上需要那么多内存。哟可以简单地给它更多的记忆。或者尝试更改算法和数据结构。

相关内容

  • 没有找到相关文章

最新更新