Недостаточно памяти при выполнении кода Java - PullRequest
1 голос
/ 15 февраля 2011

У меня есть набор данных, сохраненный в виде текстового файла, который в основном содержит векторы, сохраняемые построчно.Мой вектор размером 10k, и у меня 250 таких векторов.Каждая запись вектора является двойной.Вот пример:

Вектор 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 .....10 000 таких записей

...

...

Вектор 250 -> 0,0 1,203973 0,0 0,0 0,0 ..... 10 000 таких записей

Теперь, если я сделаю математику, это должно занять 10 КБ 16 байтов X 250 (при условии, что каждая запись вектора является двойной, занимающей 16 байтов пространства), что составляет ~ 40 МБ пространства.Однако я вижу, что размер файла отображается только 9,8 МБ.Я где-то ошибаюсь?

Дело в том, что я использую эти данные в своем коде Java.Пространственная сложность моего алгоритма O (нет записей в векторе X, нет записей).Даже когда я запускаю свой код, выделяя около 4 ГБ памяти, мне все равно не хватает места в куче.Чего мне не хватает?

Спасибо.Энди

Ответы [ 5 ]

2 голосов
/ 15 февраля 2011

После того, как так много людей догадались о размере, я сделал 3 простых теста и использовал Eclipse Memory Analyzer для определения размера. (Win7, 1.6.0_21 Java HotSpot (TM) 64-битная виртуальная машина сервера)

  • double[][] = Размер: 19,2 МБ Классы: 328 Объекты: 2,7 К
  • Double[][] structure = Размер: 76,5 МБ Классы: 332 Объекты: 2,5 м
  • ArrayList<ArrayList<Double>> = Размер: 79,6 МБ Классы: 330 Объекты: 2,5 м

256 МБ (java -Xmx256m Huge) было достаточно для запуска тестов.

Так что, я думаю, проблема не в размере, это могут быть две вещи:

  • в алгоритме есть ошибка
  • JVM не работает с 4 ГБ

Если кто-то заинтересован в коде:

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 голосов
/ 15 февраля 2011

Если мы не можем увидеть код (что достаточно справедливо), все, что я могу сказать, это использовать параметр командной строки -XX:+HeapDumpOnOutOfMemoryError при запуске приложения, а затем проанализировать полученный дамп кучи с помощью jhat.

0 голосов
/ 15 февраля 2011

Теперь, если я сделаю математику, это должно занять до 10 КБ X 16 байт X 250 места (при условии каждая запись вектора является двойным до 16 байт), что составляет ~ 40 МБ пространство. Однако я вижу, что файл Размер отображается только 9,8 МБ. Я что-то не так?

Если вы ошибаетесь, предполагается, что каждый double занимает 16 байтов пространства при сохранении в виде текста. Кажется, у вас много значений 0, которые занимают только 4 байта в строковой форме (включая разделитель).

Даже когда я запускаю свой код, выделяя как 4 ГБ памяти, я все еще не хватает куча места. Чего мне не хватает?

Это зависит от вашего кода. Одной из причин может быть то, что вы храните ваши данные в ArrayList<Double> или (что еще хуже) TreeSet<Double> - объекты-оболочки Double могут легко вызвать перегрузку памяти в 200% - и структуры Set / Map намного хуже.

0 голосов
/ 15 февраля 2011

Трудно сказать, не видя код и аргументы виртуальной машины. Но обратите внимание, что переменные в вашем алгоритме также потребляют память. И этот размер файла в зависимости от использования памяти зависит от того, как вы строите свои объекты в памяти, например, простой объект без двойного занимает самостоятельно место.

Получите подходящий инструмент для оценки использования памяти. Ознакомьтесь с дистрибутивом TPTP Eclipse .

Кроме того, вы можете проверить разреженных матриц .

0 голосов
/ 15 февраля 2011

Не видя код, я не могу сказать наверняка, но звучит так, как будто вы перераспределяете, когда вы либо) читаете данные из файла, либо б) где-то в своем алгоритме. Я бы посоветовал вам использовать такой инструмент, как visualVM, для проверки распределения ваших объектов - он сможет рассказать вам, как вы распределяете и какие ошибки делаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...