2

我在内存管理方面遇到了一些麻烦。我这里有一些代码在循环中运行 sql 查询,将数据放入数组列表中,然后进行一些计算。我之前运行过很多类似的程序都没有这个问题。我将查询放在循环中的原因是,太多的内存不会一次存储在 java 对象中。但是,现在当我运行程序时,每次都会在完全相同的位置出现内存错误(当它在循环的第 29 次迭代时)。

这是错误 -

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.util.Arrays.copyOf(Unknown Source)
at java.util.ArrayList.grow(Unknown Source)
at java.util.ArrayList.ensureCapacityInternal(Unknown Source)
at java.util.ArrayList.add(Unknown Source)
at transnMat.bootTrnsn.main(bootTrnsn.java:82)

我已经粘贴了下面的代码,我非常感谢任何关于我可能会改变以摆脱这个的提示 -

Connection conn = null;Statement st = null;ResultSet rstru = null;
for(int i=start;i<stop;i++) {
    double[][] forvariance = new double[(demos.length-1)][numsims];
    ArrayList<Long> hhids1 = new ArrayList<>();
    ArrayList<Double> outlierwt = new ArrayList<>();
    ArrayList<String> fbdemos = new ArrayList<>();
    ArrayList<String> trudemos = new ArrayList<>();
    rstru = st.executeQuery(
        "select TRUTH_DEMO_ID, FB_DEMO_ID, RN_ID, OUTLIER_WEIGHT from SCRATCH.." +
        months + "monthtable where BRAND_ID = " + brands[i] +
        " order by RN_ID");
    while (rstru.next()) { //Get query results and put them into a hash map.
        String temp0 = rstru.getString(1);
        String temp1 = rstru.getString(2);
        String temp2 = rstru.getString(3);
        String temp3 = rstru.getString(4);
        //String temp5 = rstru.getString(6);
        hhids1.add(Long.parseLong(temp2.substring(0,11)));
        fbdemos.add(temp1);
        trudemos.add(temp0);
        outlierwt.add(Double.parseDouble(temp3));
    }
    for(int sim=0;sim<numsims;sim++) {
        trnsnpv = new double[demos.length][demos.length-1];
        HashMap<Long,Integer> thissampl = bootsampl2.get(sim);
        for(int i1=0;i1<fbdemos.size();i1++) {
            if(thissampl.containsKey(hhids1.get(i1)))
                trnsnpv[dems.get(fbdemos.get(i1))][dems.get(trudemos.get(i1))-1] +=
                    outlierwt.get(i1)*(double)thissampl.get(hhids1.get(i1));
        }
        for(int j=0;j<trnsnpv.length;j++) { //27 rows
            trnsnpv[j] = normalize(trnsnpv[j]);
            for(int k=0;k<trnsnpv[j].length;k++) { //26 columns
                forvariance[k][sim] += trnsnpv[j][k];
            }
        }
    }
    for(int k = 0; k < (demos.length - 1); k++) {
        double d = StdStats.var11(forvariance[k]);
        fileIO.fileIO.write2file(brands[i] + "," + demos[k+1] +
                "," + String.valueOf(d) + "\n", "vars.csv");
    }
    System.out.println("Brands processed: " + String.valueOf(i-start) +
            " out of: " + (stop-start));
    hhids1.clear();
    outlierwt.clear();
    fbdemos.clear();
    trudemos.clear();
}
4

2 回答 2

2

这里有几个性能问题:

  1. 数据库每次都必须重新编译查询,因为 SQL 没有参数化。考虑使用准备好的语句。
  2. 嵌套循环。我看到有一个地方有 4 个嵌套循环。
  3. 由于变量名称和过多的循环,我无法弄清楚您的逻辑在做什么。如果可能,并且不确定它是否符合您的逻辑(取决于您正在执行的聚合),您是否可以在您的 while (rs.next()) 循环中一次完成一个对象的所有操作?

前任:

while (rs.next()) {
    String temp0 = rstru.getString(1);
    String temp1 = rstru.getString(2);
    String temp2 = rstru.getString(3);
    String temp3 = rstru.getString(4);
    //String temp5 = rstru.getString(6);

    // do all of your work in here, so that your objects
    // can be garbage collected before the next iteration
}
于 2013-05-17T23:53:53.843 回答
0

这是确实有效的代码版本(供我自己参考)..

for(int i=start;i<stop;i++){
            double[][] forvariance = new double[(demos.length-1)][numsims];
            trnsnpv = new double[numsims][demos.length][demos.length-1];
            int size = 0;
            Long hhids1;
            Double outlierwt;
            String fbdemos;
            String trudemos;
            rstru = st.executeQuery("select TRUTH_DEMO_ID, FB_DEMO_ID, RN_ID, OUTLIER_WEIGHT from SCRATCH.."+months+"monthtable where BRAND_ID = " + brands[i]+" order by RN_ID");
            while (rstru.next()) {//Get query results and put them into a hash map.
                String temp0 = rstru.getString(1);String temp1 = rstru.getString(2);String temp2 = rstru.getString(3);String temp3 = rstru.getString(4);
                hhids1 = (Long.parseLong(temp2.substring(0,11)));
                fbdemos = (temp1);
                trudemos = (temp0);
                outlierwt = (Double.parseDouble(temp3));
                for(int sim=0;sim<numsims;sim++){
                    HashMap<Long,Integer> thissampl = bootsampl2.get(sim);
                    if(thissampl.containsKey(hhids1))
                        trnsnpv[sim][dems.get(fbdemos)][dems.get(trudemos)-1] += outlierwt*(double)thissampl.get(hhids1);
                }
                size++;
            }
            System.out.print("Processing: " + size + " rows");
            for(int sim=0;sim<numsims;sim++){
                for(int j=0;j<trnsnpv[sim].length;j++){//27 rows
                    trnsnpv[sim][j] = normalize(trnsnpv[sim][j]);
                    for(int k=0;k<trnsnpv[sim][j].length;k++){//26 columns
                        forvariance[k][sim] += trnsnpv[sim][j][k];
                    }
                }
            }
            for(int k = 0; k < (demos.length - 1); k++){
                double d = StdStats.var11(forvariance[k]);
                fileIO.fileIO.write2file(brands[i] + "," + demos[k+1] + "," + String.valueOf(d) + "\n", "vars.csv");
            }
            System.out.print("Brands processed: " + String.valueOf(i-start + 1 ) + " out of: " + (stop-start) + "\n");
            //hhids1.clear();outlierwt.clear();fbdemos.clear();trudemos.clear();
        }
于 2013-05-18T03:05:09.880 回答