Одна и та же программа, одна и та же JVM, но совершенно разные требования к памяти и время выполнения на разных машинах — почему?

Я пытаюсь запустить симуляцию NetLogo (инфраструктура моделирования Java) в кластере как часть большой эксперимент. Я был удивлен кажущимся огромным требованием памяти для (относительно) простой симуляции. В кластере он выдает исключения «java.lang.OutOfMemoryError: пространство кучи Java» для всего, что меньше размера кучи «-Xmx2500M». Одно выполнение занимает 5 часов. Я провел один и тот же эксперимент на обоих своих компьютерах Mac (iMac и MacBook Pro), и они были выполнены менее чем за час, а «-Xmx1024» не дало ошибок. Для кластерных заданий требуется «-XX:MaxPermSize=250M», тогда как на моих компьютерах Mac не требуется увеличения выше значения по умолчанию. Я запускал один и тот же код, одни и те же входные данные, используя одни и те же банки во всех случаях.

В каждом случае используются 64-битные JVM (и, насколько я знаю, они очень похожи):

<on the cluster>
$ java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)

<on my macs>
$ java -version
java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-10M3646)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)

И я запускаю клиентскую JVM во всех случаях (изначально использовал сервер в кластере, переключение на клиент не имело значения). Я пробовал выполнять в кластере с java 7, такие же огромные проблемы с памятью и временем выполнения.

Я в полном недоумении, никто из тех, с кем я разговаривал, не может этого объяснить. Кто-нибудь там сталкивался с этим раньше? Любая помощь очень ценится!


person user1660640    schedule 10.09.2012    source источник
comment
Возможно, вам следует создать дамп кучи с помощью -XX:+HeapDumpOnOutOfMemoryError, а затем использовать MAT или аналогичный, чтобы увидеть, что использует память.   -  person Dan Gravell    schedule 10.09.2012
comment
Я бы использовал VisualVM или коммерческий профилировщик памяти, такой как YourKit.   -  person Peter Lawrey    schedule 10.09.2012
comment
мне кажется, что у вас также есть две разные версии jvm. Не говорю, что это ваша проблема, но это может способствовать.   -  person Matt    schedule 10.09.2012
comment
Спасибо всем, буду изучать дампы кучи. @Matt: вы правы, они немного отличаются. Однако я пробовал обе Java 6 и 7 JVM, и обе они давали одну и ту же проблему. Мне было бы очень странно, если бы на компьютерах Mac работала JVM, которой для выполнения той же задачи требовалось меньше половины оперативной памяти.   -  person user1660640    schedule 10.09.2012


Ответы (2)


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

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

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

person Peter Lawrey    schedule 10.09.2012
comment
Спасибо за очень быстрый ответ. Скорость ввода-вывода была одним из первых предложений. Кластер намного медленнее, и это объясняет гораздо более медленную инициализацию, чем у меня на собственных машинах. Однако программа после запуска не читает/записывает на диск до самого конца (через 5 часов) и записывает одну строку в один файл, когда это происходит. Я также должен сказать, что во время этих тестов на кластере больше никто ничего не запускал. Я посмотрю на дамп кучи, а пока есть какие-нибудь другие предложения? - person user1660640; 10.09.2012
comment
Если вы моделируете кластер, есть ли у вас сетевой ввод-вывод, даже через петлю? Данные о скорости могут передаваться по петле и сильно различаются в зависимости от процессора и ОС. - person Peter Lawrey; 10.09.2012
comment
Все задание (одно задание) выполняется на одном узле кластера: идея состоит в том, чтобы одновременно запускать несколько сотен таких заданий. Связь между узлами не требуется, каждое задание полностью автономно как собственный процесс Java. - person user1660640; 10.09.2012
comment
Как он имитирует кластер, если он не использует ввод-вывод? Вы говорите, что каждый узел полностью привязан к процессору? - person Peter Lawrey; 10.09.2012
comment
Извините, кажется, я вас запутал. Он не имитирует кластер, он работает в кластере: наборе мощных машин (узлов кластера), предназначенных для проведения массовых экспериментов. Узлы делят дисковое пространство, отсюда возможная проблема медленного ввода-вывода, которую я не считаю основной причиной. Кластеры могут запускать задания, охватывающие несколько узлов (это то, о чем я думал, вы спрашивали после того, как проблема заключалась в вводе-выводе между узлами), но конкретные задания, которые я выполняю, представляют собой автономные программы Java. Я могу запускать их на своих машинах так же, как и на кластере. Разница в том, что кластер может одновременно запускать сотни - person user1660640; 10.09.2012
comment
Я бы попробовал запустить кластер только с одним узлом и посмотреть, как ведет себя диск, например. с помощью vmstat или iostat. Если кластер использует общий диск между 100 узлами, даже небольшое количество операций ввода-вывода может добавиться. - person Peter Lawrey; 10.09.2012
comment
Хорошо, спасибо. Мне нужно спешить сейчас, но я посмотрю немного позже. - person user1660640; 10.09.2012

Я подозреваю, что проблема в том, что вы используете сервер JVM. Клиентская JVM недоступна на 64-битных машинах. Даже если вы попросите клиентскую JVM, она даст вам серверную.

person Eric Pabst    schedule 19.09.2013