2014-02-10 3 views
3

У меня есть Java-программа, которая работает на (большом) графике. Таким образом, он использует значительное количество пространства кучи (~ 50 ГБ, что составляет около 25% от физической памяти на главной машине). В какой-то момент программа (неоднократно) выбирает один узел из графика и выполняет некоторые вычисления с ним. Для некоторых узлов это вычисление занимает гораздо больше времени, чем ожидалось (30-60 минут, а не ожидаемые несколько секунд). Чтобы профилировать эти операции, чтобы узнать, что занимает так много времени, я создал тестовую программу, которая создает только очень небольшую часть большого графа, а затем выполняет ту же операцию на одном из узлов, которые занимали очень много времени, чтобы вычислить в оригинальная программа. Таким образом, в тестовой программе, очевидно, используется очень мало кучи, по сравнению с исходной программой.Java медленнее с большой кучей

Оказалось, что операция, которая заработала 48 минут в исходной программе, может быть выполнена за 9 секунд в тестовой программе. Это меня действительно смущает. Первая мысль может заключаться в том, что большая программа тратит много времени на сборку мусора. Поэтому я включил подробный режим сборщика мусора VM. Согласно этому, полные сборки мусора не выполняются в течение 48 минут, и только около 20 коллекций в молодом поколении, каждый из которых занимает менее 1 секунды.

Так что мои вопросы - что еще может быть, что объясняет такую ​​огромную разницу во времени? Я не знаю много о том, как Java внутренне организует кучу. Есть ли что-то, что занимает значительно больше времени для большой кучи с большим количеством живых объектов? Может ли быть, что выделение объектов занимает гораздо больше времени в такой настройке, потому что для нахождения подходящего места в куче требуется больше времени? Или VM делает внутреннюю реорганизацию кучи, которая может занять много времени (помимо сбора мусора, очевидно).

Я использую Oracle JDK 1.7, если это имеет значение.

+3

Не зная, какие операции выполняет ваша программа, на это невозможно ответить. –

+0

Как иначе тест и основная программа отличаются от количества выделяемой кучи? Работают ли они на других типах данных? Сколько кучи использует тестовое приложение, есть опция производительности для использования коротких указателей, если используется только небольшая куча (но это никоим образом не может объяснить вашу разницу в производительности) – ooxi

+0

Вы должны использовать хороший профилировщик (например, YourKit) для проанализируйте причину медленности, мне трудно поверить, что кто-то здесь может догадаться, каковы источники проблемы. – alfasin

ответ

3

Хотя большая память может означать большие проблемы, я бы сказал, что нет ничего (кроме GC, который вы исключили), что может увеличиться от 9 секунд до 48 минут (коэффициент 320).

Большая куча создает, по-видимому, худшую пространственную локальность, но я не думаю, что это имеет значение. Я не согласен с ответом Тима w.r.t. «, чтобы оставить кэш на все».

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

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

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

+0

Насколько я могу судить, никаких обменов не происходит. Основываясь на вашем ответе, я могу только предположить, что проблема лежит где-то в моем коде. Мне придется еще раз исследовать. Благодаря! – Georg

0

Даже если все в памяти, у вас есть несколько уровней кэширования данных на современных процессорах. Каждый раз, когда вы оставляете кеш для получения данных медленнее, что будет идти. Наличие 50 ГБ оперативной памяти вполне может означать, что он должен оставить кеш для всего.

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

Лучший совет, которым я могу пять, чтобы попытаться запустить профайлер против него, когда он работает медленно, и когда он работает быстро и сравнивает разницу.

Вам нужны твердые цифры и тайминги. «В этой среде X выполнял время Y». Из этого вы можете начать сужаться.

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