2015-12-05 2 views
-1

Я решаю проблему на spoj, и система показывает, что моя программа взяла 1341M памяти. Когда я смотрю материалы на других языках, они требуют ~3M, что примерно в 400 раз меньше!Большая занимаемая память на простом Java-коде

Мой код ниже:

class Main { 
    static List<BigInteger> numbers = new ArrayList<>(); 

    static { 
     BigInteger max = BigInteger.TEN.pow(100); 

     numbers.add(BigInteger.ONE); 
     numbers.add(BigInteger.valueOf(2l)); 
     BigInteger last = numbers.get(1); 

     while (last.compareTo(max) <= 0) { 
      numbers.add(numbers.get(numbers.size() - 1).add(numbers.get(numbers.size() - 2))); 
      last = numbers.get(numbers.size() - 1); 
     } 
    } 

    public static void main(String[] args) throws java.lang.Exception { 
     BufferedReader bi = new BufferedReader(new InputStreamReader(System.in)); 
     String line; 
     String delims = " "; 
     while ((line = bi.readLine()) != null) { 
      StringTokenizer tokenizer = new StringTokenizer(line, delims); 
      BigInteger from = new BigInteger(tokenizer.nextToken()); 
      BigInteger to = new BigInteger(tokenizer.nextToken()); 

      if (from.equals(BigInteger.ZERO) && to.equals(BigInteger.ZERO)) { 
       return; 
      } else { 
       System.out.println(countInRange(from, to)); 
      } 
     } 
    } 

    public static int countInRange(BigInteger from, BigInteger to) { 
     int fromIndex = Collections.binarySearch(numbers, from); 
     fromIndex = fromIndex < 0 ? Math.abs(fromIndex) - 1 : fromIndex; 
     int toIndex = Collections.binarySearch(numbers, to); 
     toIndex = toIndex < 0 ? Math.abs(toIndex) - 1 : toIndex + 1; 
     return toIndex - fromIndex; 
    } 
} 

Я полагаю, что BufferedReader является причиной высокого потребления памяти. Возможно ли в этом случае значительно улучшить память? Я не говорю о достижении 3M, но, по крайней мере, находясь под 100M или около того.

+0

Чтобы воспроизвести проблему, вам необходимо знать входные данные программы. – Armali

ответ

1

Прежде всего: Как элементы, которые вы храните в numbers? Может быть довольно немного, так как ваш максимум равен 10 pow 100.

Второй: Рассмотрим модель памяти Java. 1341M примерно столько же, сколько подходит для 32-битной виртуальной машины Java. Так что, возможно, это просто то, что вы генерируете объекты в куче (все эти блестящие new BigInteger), Java произвела много памяти для мусора. Но если вы не установите параметры для своего процесса правильно, он не вернет его ОС.

Вы фактически пытались запустить программу только с 100M памяти (установив -Xmx100m опцию в вашем Java вызов?

Рассмотрите возможность создания дампа кучи и проверить, что (я рекомендую Eclipse Memory Profiler посмотреть, что ест память . Моя догадка на данный момент: Это либо огромное количество предварительно вычисленных чисел (?, что они Кажется, последовательность Лукаса мне?) или просто мусор ждет, чтобы быть собраны

1

Быстрая проверка:. Вы уверены, 1341 МБ памяти фактически не потребляются вашей IDE (например, Eclipse или Netbeans)?

Я упаковал ваш код в исполняемый Jar на компьютере под управлением Windows 7, x64 с 64b Oracle JRE 1.8.0.66. При запуске кода система отображает только потребление памяти ~ 10 МБ. Я генерируется дампа кучи с помощью:

java -agentlib:hprof=file=snapshot.hprof,format=b -jar number_counter.jar 

При анализе этого с анализатором памяти Eclipse,, след память используемых объектов была очень низкой.

Несколько замечаний:

  • номер массив не должен быть очень большим. Насколько я понял, он содержит только последовательность Фибоначчи, которая растет довольно быстро, поэтому я видел только 500 хранимых BigNumbers.
  • Нет никакой реальной причины, почему BufferedReader должен иметь большой след. Это сильно используемый объект, и я уверен, что в него были вложены большие усилия по оптимизации.

В заключение, пожалуйста, убедитесь, что ваш мониторим правильный процесс Java, убедитесь, что вы используете последнюю дату JRE и убедитесь, что вы не используете некоторые ненужные правила управления памятью. Ваш код кажется прекрасным, а размер отпечатка должен быть меньше 20 МБ.

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