2012-01-03 2 views
0

Я делаю Koch fractal snowflake в java и сохраняю его в svg-файле.фракталы и "java.lang.OutOfMemoryError: Java heap space"

Я делаю это, запоминая фрактал с помощью класса LineStrip2D (это оболочка ArrayList из Vec2D, которая реализует итерацию).

Основная функция это одна:

public static LineStrip2D repeatPatternIntoLineStrip2D(
     LineStrip2D pattern, 
     LineStrip2D polygon, 
     boolean repeatUp) { 

    /* 
    * pattern: must be a pattern between Vec(0,0) and Vec(1,0) 
    *   (normalized beetween 0-1 and in X axis) 
    * */ 

    float angle, distance; 
    Vec2D pivot, a, b, direction, b1; 
    LineStrip2D new_polygon = new LineStrip2D(); 

    new_polygon.add(pattern.vertices.get(0)); 
    a = polygon.vertices.get(0); 

    int count=0; 
    for (int i = 1; i < polygon.vertices.size(); i++) { 
     b = polygon.vertices.get(i); 
     a = polygon.vertices.get(i-1); 

     distance = b.distanceTo(a); 
     direction = b.sub(a).normalize(); 
     angle = PApplet.atan2(direction.y, direction.x); 
     pivot = a; 

     for (int j = 1; j < pattern.vertices.size(); j++) { 
      Vec2D _b1 = pattern.vertices.get(j); 

      b1 = _b1.copy() ; 

      if(repeatUp)b1.y *= -1;    
      b1.scaleSelf(distance); 
      b1 = b1.rotate(angle); 
      b1.addSelf(pivot); 

      new_polygon.add(b1); 
      count++; 
     } 
     a = b; 
    } 
    System.out.println(count); 
    return new_polygon; 
} 

У меня есть образец с исходной кривой Коха:

enter image description here

И я призываю:

pattern = GeometryHelper.repeatPatternIntoLineStrip2D(pattern, pattern, false); 

Теперь проблема :

После нескольких итераций (851968) У меня есть java.lang.OutOfMemoryError: Java куча пространства. Как я могу избежать этой ошибки и получить огромный файл svg? Я думаю, что я могу сделать этот процесс разными способами, но я не понимаю, как его реализовать разумным образом.

ответ

0

Прежде всего, почему вы используете переменную count? Вы можете заменить его на System.out.println(polygon.vertices.size() * polygon.vertices.size()); и удалить бесполезную операцию с увеличением count.

Для вашего отказа от ошибки памяти, попробуйте увеличить размер кучи вашего VM

+0

Я сомневаюсь, что устранение одной переменной позволит решить проблемы с размером кучи. –

+1

Я имею в виду тот факт, что у него есть некоторые бесполезные операции в его коде –

+0

@ Jason482: +1 для противодействия -1: ответ правильный, содержит дополнительную информацию, которая может быть полезна, и была на самом деле * первой * правильной ответ (хотя и немного менее подробно, чем другой). Не достоин нисходящего потока, ИМХО. – Mac

3

Первый и самый простой, чтобы дать JVM больше памяти. Добавление -Xmx = 1g может быть достаточно (и будет работать на большинстве машин в настоящее время). Не стесняйтесь добавлять больше, если вам нужно больше, до тех пор, пока оно не превысит то, что доступно на вашем компьютере.

Это, как говорится, касается фракталов, ВСЕГДА будет верхний предел, который вы нанесли на использование памяти. Сначала вы должны профилировать свое приложение, чтобы узнать, где используется вся память. Как только вы обнаружите это, вы можете подумать о том, чтобы переработать проблему, чтобы быть более дружественной к памяти. Или вы можете перейти к дизайну, который выполняет итерацию и сохраняет результаты на диске между итерациями для сохранения памяти из предыдущих итераций.

2

Как уже упоминалось, первым шагом является попытка выяснить, можно ли достичь количества итераций, которые вы хотите, только изменив размер кучи JVM (это параметр командной строки -Xmx = ... где .. . - максимальный объем памяти, который вы хотите выделить). Если у вас достаточно ОЗУ на вашем компьютере, вы можете установить это довольно высокое (и, возможно, есть способ заставить JVM использовать пространство подкачки диска, поэтому он может быть безумно высоким, но я не знаю, как это сделать/если это возможно).

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

+0

Где я могу найти некоторое объяснение того, как реализовать сериализацию в стеке? – nkint

+0

Я снова в этом проекте, и это кажется лучшим решением, которое я могу реализовать. но я не понял его полностью .. Невозможно получить дальнейшее объяснение или пример? – nkint

+0

@nkint Что вы сейчас установили размер кучи? Сколько у вас RAM на вашем компьютере? –

1

Я полагаю, что проблема связана с классом LineStrip2D, инкапсулирующим ArrayList: реализация этого списка является backend массивом, размер которого растет линейно (как указано здесь ArrayList: how does the size increase?). Я считаю, что вы исчерпали память, потому что ArrayList выделяет полный новый массив с этим новым размером, сохраняя старый (http://en.wikipedia.org/wiki/Dynamic_array). Итак, для завершения рисования вам потребуется не менее 2 * MAX_SIZE. Вы должны увеличить общую кучу, но переход на LinkedList должен улучшить ситуацию.

Смежные вопросы