Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Размер памяти JVM, как сделать адекватным задаче? 
V
    Опции темы
Дрон
Дата 27.5.2008, 17:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



Очередной неприятный сюрприз от Java.

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

Если указать параметр -Xmx1024m, то JVM по ходу работы радостно занимает всю эту память, не вызывая сборщик мусора, даже когда память уже не нужна. При этом если я тестирую на своём ноутбуке у которого всего 1.25 Гб памяти, то Windows радостно уходит в своп, делая работу с приложением просто невозможной.
Если указать меньший предел для кучи, то до свопа не доходт и сборщик мусора всё отлично очищает. Но, к сожалению, при этом есть вероятность, что какая-нибудь огромная фотография просто не влезет в ограниченный объём памяти и мы получим OutOfMemory, хотя на компьютере может и 4 Гб памяти быть установлено.

Что делать?




--------------------
Да. Именно так.
PM   Вверх
LSD
Дата 27.5.2008, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Если это не сервер и кратковременная заморозка приложения не страша, периодически вызывай System.gc(). Если JVM запущена не в серверном режиме, то память будет отдаваться.

Tuning Garbage Collection with the 5.0 Java Virtual Machine.



--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
COVD
Дата 27.5.2008, 18:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



Цитата

JVM по ходу работы радостно занимает всю эту память, не вызывая сборщик мусора, даже когда память уже не нужна.


Возможно, это зависит от типа gc. У меня Xmx = 256 (Xms не задана), но приложение крутится с текущей памятью ~ 5, и дефолтный gc радостно чистит, о чем сообщает в лог. Другое дело, если понадобится больше памяти, то потом JVM под виндоуз врядли отдаст в систему освободившуюся память. На Солярисе отдает.  

Это сообщение отредактировал(а) COVD - 27.5.2008, 18:16
PM MAIL   Вверх
Дрон
Дата 27.5.2008, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



Цитата(LSD @  27.5.2008,  18:03 Найти цитируемый пост)
Если это не сервер и кратковременная заморозка приложения не страша, периодически вызывай System.gc(). Если JVM запущена не в серверном режиме, то память будет отдаваться.

Да я вот уже подумал завести отдельный поток, который только тем и будет заниматься, что следить за состоянием приложения (занято ли оно чем-то полезным) и периодически дёргать сборщих мусора. Только мне казалось, что он сам должен этим заниматься.



Добавлено через 10 минут и 21 секунду
Цитата(COVD @  27.5.2008,  18:10 Найти цитируемый пост)
У меня Xmx = 256 (Xms не задана), но приложение крутится с текущей памятью ~ 5, и дефолтный gc радостно чистит, о чем сообщает в лог.

Вот это мне и не понятно. Ладно бы он нормально чистил память, тогда я и на ограничение Xmx я не жаловался, но почему-то вместо это получается только постоянный жор, пока не упрётся в предел.

И мне даже не очень-то и нужно, чтобы память обратно в систему отдавалась -- мне гораздо важнее, чтобы куча JVM не росла без надобности.

Это сообщение отредактировал(а) Дрон - 27.5.2008, 18:20


--------------------
Да. Именно так.
PM   Вверх
powerOn
Дата 27.5.2008, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата(Дрон @  27.5.2008,  18:52 Найти цитируемый пост)
Если указать параметр -Xmx1024m, то JVM по ходу работы радостно занимает всю эту память, не вызывая сборщик мусора, даже когда память уже не нужна.


 Может у тебя в коде ошибки и где-то идёт накопление висячих ссылок. Вот вся память и уходит.


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
COVD
Дата 27.5.2008, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



Цитата

не вызывая сборщик мусора

Это легко проверяется активацией лога gc. Например, указанием параметра JVM "-Xloggc:" . В консоль тогда будут выдаваться сообщения о запусках gc. Если gc запускается, но убрать ничего не может, значит "утечка" памяти, надо код анализировать. 

Это сообщение отредактировал(а) COVD - 27.5.2008, 18:46
PM MAIL   Вверх
Дрон
Дата 27.5.2008, 18:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



Цитата(COVD @  27.5.2008,  18:43 Найти цитируемый пост)
Это легко проверяется активацией лога gc. Например, указанием параметра JVM "-Xloggc:" . В консоль тогда будут выдаваться сообщения о запусках gc. Если gc запускается, но убрать ничего не может, значит "утечка" памяти, надо код анализировать. 

Спасибо. Попробуем.
Однако я сомневаюсь в том что проблема в коде -- ведь когда я уменьшаю max heap, например, до 700 мегабайт, то у меня приложение продолжает отлично работать освобождая память от старых фотографий по мере загрузки новых. Значит проблем с утечкой быть не должно.

Это сообщение отредактировал(а) Дрон - 27.5.2008, 18:52


--------------------
Да. Именно так.
PM   Вверх
LSD
Дата 27.5.2008, 19:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Какую JVM запускаешь, клиентскую или серверную?


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Дрон
Дата 27.5.2008, 19:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



Цитата(LSD @  27.5.2008,  19:00 Найти цитируемый пост)
Какую JVM запускаешь, клиентскую или серверную? 

Клиентскую. Из JDK к 5-й Java, на 6-й ещё подробно не экспериментировал.
Из всех параметров, что я передаю -- только установки памяти: -Xms128m -Xmx1024m.

Надо действительно попробовать включить лог GC. Мне тоже кажется, что в нормальных условиях не должно быть такого неконтролируемого роста памяти. Может дело ещё в каких-то особенностях моей программы.

Вот такой вопрос: если я буду, например, в цикле грузить большие картинки, сразу же "забывая" (т.е. не сохраняя ссылку) полученный результат, то память должна расти до предела или gc должен регулярно освобождать большой объём ненужных данных?

Это сообщение отредактировал(а) Дрон - 27.5.2008, 19:08


--------------------
Да. Именно так.
PM   Вверх
Дрон
Дата 27.5.2008, 21:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



Сделал логи и разобрался. Мой изначальный вывод отчасти подтверждается -- память освобождается только когда становится совсем нечего больше кушать. Причём освобождается весьма радикально -- сразу почти весь гигабайт срезала, но размер VM в диспетчере задач остался тот же:
Цитата

91.405: [GC 647826K->628503K(963636K), 0.0098166 secs]
91.415: [Full GC 628503K->628350K(963636K), 0.1711285 secs]
234.038: [GC 998417K->941405K(1040512K), 2.2270789 secs]
244.703: [GC 1005917K->944177K(1040512K), 1.1466133 secs]
275.299: [GC 972973K->938974K(1040512K), 0.9909746 secs]
276.317: [Full GC 938974K->938974K(1040512K), 10.6697245 secs]
286.987: [Full GC 938974K->15113K(1040512K), 2.6638785 secs] -- во как!  smile 
387.274: [GC 385435K->327528K(1040512K), 0.3283753 secs]

Обратите внимание на огромный перерыв между двумя последними -- система ушла в глубокий своп и практически не отвечала несмотря на то, что память уже была очищена. 

Я теперь уже понял, что в тестируемой версии этого и стоило ожидать -- картинки кэшируются через SoftReference, которые живут до тех пор, пока не потребуется память. Проблема в том, что такое поведение, как мне кажется, наблюдалось ещё когда я даже не знал что такое SoftReference. Надо больше экспериментов. Если же дело только в SoftReference, то никаких проблем, это легко исправить -- надо самому контролировать свободную память и очищать кэш, при её отсутствии.

Вывод такой -- по воле создателей виртуальной машины GC старается как можно меньше работать, и ему даже наплевать, что программа становится практически неработоспособна из-за отсутствия памяти smile

Раз уж особенность JVM состоит в том, что у неё есть искуственное ограничение максимального объёма кучи, то я бы ещё предпочёл иметь возможность указать промежуточный параметр -- например 512 мегабайт, которые превышать не желательно. И чтобы GC старался их не превышать, если это возможно. Но раз такого параметра нет, то надо делать как-то вручную, а поскольку в Java нельзя узнать объём физической памяти, то на машинам с её недостатком будет работать очень плохо, а с избытком не будет использовать все возможности. Эх...

Ну и, кстати, не я один сильно озабочен этой проблемой: http://bugs.sun.com/view_bug.do?bug_id=4408373
Этому "багу" уже больше семи лет.

Это сообщение отредактировал(а) Дрон - 27.5.2008, 22:49


--------------------
Да. Именно так.
PM   Вверх
LSD
Дата 28.5.2008, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Память системе возвращается, но после принудительного вызова сборщика мусора:
Код

  @SuppressWarnings("unchecked")
  public static void main(String[] args) throws Exception
  {
    final int COUNT = 10;
    SoftReference bytes[] = new SoftReference[COUNT];
    printMemoryStat();
    for(int i = 0; i < COUNT; i++)
    {
      bytes[i] = new SoftReference(new byte[64 * 1024 * 1024]);
      printMemoryStat();
    }
    bytes = null;
    System.out.printf("%nClear memory%n%n");
    System.gc();
    printMemoryStat();
    System.gc();
    printMemoryStat();
    System.gc();
    printMemoryStat();
  }

  private static void printMemoryStat()
  {
    Runtime runtime = Runtime.getRuntime();
    long freeMemory = runtime.freeMemory();
    long totalMemory = runtime.totalMemory();
    long usedMemory = totalMemory - freeMemory;
    System.out.printf("free: %1$,12d    used: %2$,12d    total: %3$,12d%n", freeMemory, usedMemory, totalMemory);
  }

Код

free:    4 554 648    used:      622 696    total:    5 177 344
free:    4 957 528    used:   67 332 776    total:   72 290 304
free:   53 344 520    used:  134 432 504    total:  187 777 024
free:   39 356 632    used:  201 541 416    total:  240 898 048
free:   92 551 728    used:  268 649 936    total:  361 201 664
free:   25 045 208    used:  336 156 456    total:  361 201 664
free:  117 422 544    used:  402 867 760    total:  520 290 304
free:   49 743 800    used:  470 546 504    total:  520 290 304
free:  452 979 080    used:   67 311 224    total:  520 290 304
free:  385 300 336    used:  134 989 968    total:  520 290 304
free:  318 191 456    used:  202 098 848    total:  520 290 304

Clear memory

free:  468 572 880    used:      202 032    total:  468 774 912
free:  282 872 528    used:      202 032    total:  283 074 560
free:    4 979 408    used:      202 032    total:    5 181 440



--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Дрон
Дата 28.5.2008, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



Цитата(LSD @  28.5.2008,  13:32 Найти цитируемый пост)
Память системе возвращается, но после принудительного вызова сборщика мусора

Да, к этому я и пришёл.

Сделал свой кэш самоочищащющимся после достижения определённого размера в памяти (правда память там оценивается весьма условно, но вроде близко к истине), но принудительный вызов сборщика мусора всё равно нужен -- даже когда я убираю все ссылки, память не торопится очищаться (ну и ладно), а продолжает расти по мере появления новых данных (вот это плохо).

В общем, сейчас у меня программа настроена так: максимальный объём 1 Гигабайт, но внутренний кэш программно ограничен 300 мегабайтами. И это меня более-менее устраивает -- в этот кэш влезет порядка 10 картинок, при этом в случае крайней необходимости программа может взять достаточно много памяти, а по ходу нормальной работы не будет разжираться.
С другой стороны это я фактически ориентируюсь на худший случай, а вот если на машине установлено, например, 4 Гигабайта памяти, то я предпочёл бы иметь гораздо больший кэш. Но похоже, что это принципиальная проблема в Java.

LSD, спасибо.



Это сообщение отредактировал(а) Дрон - 28.5.2008, 13:52


--------------------
Да. Именно так.
PM   Вверх
w1nd
Дата 28.5.2008, 22:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вертилятор
***


Профиль
Группа: Завсегдатай
Сообщений: 1077
Регистрация: 22.3.2006
Где: Москва

Репутация: 20
Всего: 54



Моя практика показывает, что для идеального поведения GC ему следует помогать, обнуляя ссылки вручную и не допуская возникновения перекрёстных ссылок в дохлых объектах.


--------------------
user posted imageuser posted image
PM MAIL ICQ   Вверх
Platon
Дата 29.5.2008, 06:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



w1nd, вот это интересно. Если какая-нибудь брошюрка-руководство в каких случаях стоит вручную обнулять (один случай выявили: про перекрестные ссылки).
Ведь не буду же я, кодируя очередной метод класса, в его конце обнулять все локальные объекты, которые я создал в процессе работы метода.
PM MAIL ICQ   Вверх
w1nd
Дата 29.5.2008, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вертилятор
***


Профиль
Группа: Завсегдатай
Сообщений: 1077
Регистрация: 22.3.2006
Где: Москва

Репутация: 20
Всего: 54



Цитата(Platon @  29.5.2008,  06:12 Найти цитируемый пост)
Ведь не буду же я, кодируя очередной метод класса, в его конце обнулять все локальные объекты, которые я создал в процессе работы метода.

Дык нужные места нужно выяснять, вооружившись профайлером. Обычно в визуальных компонентах бякость случается.


Это сообщение отредактировал(а) w1nd - 29.5.2008, 10:35


--------------------
user posted imageuser posted image
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1047 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.