【问题标题】:Any idea why my class takes much more memory than it is supposed to?知道为什么我的课需要比预期更多的内存吗?
【发布时间】:2019-08-20 03:49:27
【问题描述】:

我正在尝试创建一个充当 X 维 ArrayList 的类,它将包含我的 X 维函数的输出。 该类工作正常,但内存消耗比应有的高得多,因此我不能将它用于太高维度的太多值。

我考虑过从 double 更改为 float,但我不允许在此项目中使用 float。

public ArrayList<XDimensionArray> inception = new ArrayList<XDimensionArray>();

public ArrayList<Double> HistoricInputs= new ArrayList<Double>();
public ArrayList<Double> inputs = new ArrayList<Double>();
public ArrayList<Double> outputs= new ArrayList<Double>();
private int dimensionCourante;
private int dimensionMax;

public XDimensionArray(ArrayList<Pair> Tab_Limites,int _dimensionCourante,int precision,ArrayList<Double> _HistoricInputs)
{
    HistoricInputs = _HistoricInputs;
    dimensionCourante = _dimensionCourante;
    dimensionMax = Tab_Limites.size();
    for(Double i = Tab_Limites.get(dimensionCourante - 1).min; i < Tab_Limites.get(dimensionCourante - 1).max; i += 1./precision)
    {
        inputs.add(i);
        if (dimensionCourante < dimensionMax)
        {
            ArrayList<Double> temp = new ArrayList<Double>();
            temp.addAll(HistoricInputs);
            temp.add(i);
            inception.add(new XDimensionArray(Tab_Limites,dimensionCourante + 1,precision,temp));
        }
        if (dimensionCourante == dimensionMax)
            outputs.add(SetOutput(i));
    }
}

代码解释:你调用给它的类

  • 代表轴的最小/最大管的数组,类根据该数组的大小猜测最大维度。
  • 要生成的当前维度(第一次调用始终为 1)
  • 表示每单位轴将创建多少点的精度(在轴 -5;5 上,精度为 10 我们得到 100 个点,每个点之间为 0.1) - 当我们处于较低维度时,输入的历史记录让我们知道谁是 Xdimension 数组的父母(基本上当您处于第 6 维 XdimArray 时,您知道哪些 XdimArrays 是您的父母“Xdim[0][8][例如 4][2][10]"。

对于我们想要在轴上创建的每个点,

-如果这不是最低维度,我们用低一维的新对象填充我们的 XdimensionArray 数组

-如果这是最低维度,我们最终填充输出数组。

为每个轴和 4 个轴运行 100 个值的程序意味着 100^4 个值(双)应该使用 100Mo 的内存对吗?但是我的程序耗尽了我给他的所有内存(2.2Go),仍然不够。

3 维中的 100 值应该意味着 10^6 双打 = 1Mo 程序实际用了500Mo(至少能跑)

编辑:我尝试跟踪 4 个维度中发生的情况,每个轴有 100 个值。程序创建第一个第一维数组,然后创建 100 个第二维数组中的 26 个(以及它们所有的第 3 和第 4 维数组),然后采用所有 2Go 并且程序停止

【问题讨论】:

  • 欢迎来到 SO!你是如何测量内存使用量的? “我的程序耗尽了我给他的所有内存,但仍然不够” - 你得到 OutOfMemoryError 了吗?
  • 我刚用了任务管理器。另外我得到的错误是关于堆内存的,虽然我不知道我是怎么得到它的,现在程序只是在我运行它时停止而不是返回错误
  • 任务管理器可能是骗人的,它显示了分配给JVM进程的内存多少,并不意味着内存实际使用了。您是否尝试使用一些标志运行该应用程序?如果最大堆大小不足,设置 -Xmx2g 可能会有所帮助。
  • 我确实在我的 Eclipse 客户端中运行了 -Xms1024M -Xmx2304M 设置。我的意思是我知道没有足够的内存来创建数组,因为程序永远不会完成创建它,并且进程占用的内存在某些时候仍然停滞不前。

标签: java oop optimization memory-management heap-memory


【解决方案1】:

1004 确实是一亿。列表中有 1 亿个条目,而不是 1 亿字节。

double 是 8 个字节的内存。但是你不使用double,你使用java.lang.Double,它是一个对象,而不是原始值。我相信一个对象头是 16 个字节,所以 16+8 是 24 个字节。

并且您的 ArrayList 包含每个 Double 的 4 到 8 个字节的引用数组(取决于您是 32 位还是 64 位 VM 以及您是否使用压缩指针),因此每个 double 需要 28-32 个字节。

这意味着您需要 2.8Gb(SI 单位)到 3.2Gb 的内存。

【讨论】:

  • 感谢您的回答!看来我必须使用 java.lang.Double 来制作我的 ArrayLists。您是否知道我可以如何继续使用原始类型或其他想法来减少内存使用? (我对内存使用问题很新,所以我在编程时从未想过它)另外,仍然 3.2Gb 的内存只有大约 400Mo,我的程序使用超过 2Go
  • 您可以使用double (double[]) 的数组来代替ArrayList&lt;Double&gt;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-31
  • 2020-01-28
  • 1970-01-01
  • 2021-04-28
  • 2016-12-02
  • 1970-01-01
  • 2011-11-08
相关资源
最近更新 更多