2011-02-15 118 views
1

我有一个保存为文本文件的数据集,它基本上包含一行一行地存储的向量。我的矢量尺寸为10k,我有250个这样的矢量。每个向量条目都是双精度。下面是一个例子:运行Java代码时内存不足

矢量1 - > 0.0 0.0 0.0 0.439367 0.0 ..... 10K这样的条目

向量2 - > 0.0 0.0 0.0 0.439367 0.0 0.0 0.0 0.0 ..... 10K这样的条目

...

...

矢量250 - > 0.0 1.203973 0.0 0.0 0.0 ..... 10K这样的条目

现在,如果我做数学题,这要占用10K X 16字节X 250空间(假设每个向量条目是一个占用16个字节的空间),这是〜40MB的空间。但是我看到文件大小仅显示为9.8MB。我在哪里错了?

事情是我在我的Java代码中使用这些数据。我的算法的空间复杂度是O(向量X中没有条目)。即使当我通过分配4GB内存来运行我的代码时,我仍然没有足够的空间。我错过了什么?

谢谢。 Andy

+6

不可能说没有看到代码。 – 2011-02-15 19:04:27

+0

顺便说一句,`double`只有8个字节长,但这在很大程度上是不相关的,而我们看不到代码。 – biziclop 2011-02-15 19:06:24

回答

2

经过这么多人猜测的大小,我做了3个简单的测试,并使用Eclipse Memory Analyzer来确定大小。 (Win7的,1.6.0_21爪哇热点(TM)64位服务器VM)

  • double[][] =大小:19,2 MB类:328个对象:2,7k
  • Double[][] structure =大小:76.5 MB类:332个对象:2.5米
  • ArrayList<ArrayList<Double>> =大小:79,6 MB类:330个对象:2.5米

256MB(java -Xmx256m Huge),都足以运行测试。

所以我想问题不在于大小,也可能是两件事情:

  • 没有在算法
  • 错误的JVM并不拥有4GB

运行

如果有人对代码有兴趣:

import java.util.ArrayList; 
import java.util.List; 

public class Huge { 

    private static final int NUMBER_OF_VECTORS = 250; 
    private static final int VECTOR_SIZE = 10000; 

    //Size: 19,2 MB Classes: 328 Objects: 2,7k 
    public static void doulbeArray() { 

     double[][] structure = new double[NUMBER_OF_VECTORS][]; 

     for(int i = 0; i < NUMBER_OF_VECTORS; i++) { 
      structure[i] = new double[VECTOR_SIZE]; 
     } 
    } 

    //Size: 76,5 MB Classes: 332 Objects: 2,5m 
    public static void doubleWrapperArray() { 

     Double[][] structure = new Double[NUMBER_OF_VECTORS][]; 

     for(int i = 0; i < NUMBER_OF_VECTORS; i++) { 
      structure[i] = new Double[VECTOR_SIZE]; 
      for (int k = 0; k < VECTOR_SIZE; k++) { 
       structure[i][k] = Double.valueOf(Math.random()); 
      } 
     } 
    } 

    //Size: 79,6 MB Classes: 330 Objects: 2,5m 
    public static void list() { 

     List<List<Double>> structure = new ArrayList<List<Double>>(); 

     for(int i = 0; i < NUMBER_OF_VECTORS; i++) { 
      List<Double> vector = new ArrayList<Double>();    
      for (int k = 0; k < VECTOR_SIZE; k++) { 
       vector.add(Double.valueOf(Math.random())); 
      } 
      structure.add(vector); 
     } 
    } 
} 
0

没有看到代码,我不能肯定地说,但是当你或者a)从文件读取数据或者b)在你的算法的某个地方,听起来就像是过度分配。我建议你使用诸如visualVM之类的工具来检查你的对象分配 - 它可以告诉你你是如何分配的以及你所犯的错误。

0

现在,如果我做数学题,应该采取 高达10K X 16字节×250的空间(假设 每个矢量条目是空间的双重考虑 高达16字节),这是〜的 空间40MB。但是我看到文件 大小仅显示为9.8MB。我在哪里 出错了?

你错在哪里是假设每个double保存为文本时需要16个字节的空间。你似乎有很多0值,只有4个字节的字符串形式(包括分隔符)。

即使我通过像4GB的内存分配 运行我的代码,我还是跑出来的 堆空间。我错过了什么?

这取决于你的代码。其中一个原因可能是您将数据存储在ArrayList<Double>或更糟的TreeSet<Double> - 包装对象将导致200%的内存开销 - 并且Set/Map结构更差。

0

很难说没有看到代码和VM参数。但请注意,算法中的变量也会消耗内存。该文件大小与内存使用情况取决于如何构建内存中的对象,例如,没有双重内存的简单对象会占用自己的空间。

获得基准测试内存使用情况的适当工具。请查看TPTP Eclipse distribution

另外,你可能想看看sparce matrixes

0

如果我们看不到代码(这很公平),我只能说在启动应用程序时使用-XX:+HeapDumpOnOutOfMemoryError命令行选项,然后使用jhat分析生成的堆转储。