Java Hashtable проблема многих обращений - PullRequest
2 голосов
/ 13 июля 2010

Я разрабатываю инструмент, который берет код Java и генерирует код для получения оценок времени выполнения основных блоков, циклов и методов. После того, как какой-то блок выполнен, мы добавляем время нашему инструменту. Модель программы сохраняется в следующем представлении

static Hashtable<String, Hashtable<Integer, Hashtable<String, pair>>> method2Data = new Hashtable<String, Hashtable<Integer, Hashtable<String, pair>>>();

static Hashtable<String, Vector<String>> class2Method = new Hashtable<String, Vector<String>>();

и время, указанное методом

 public static void addBlock(int id, double time, String meth, String thread);

Но у меня следующая проблема. При каждом вызове addBlock мы берем что-то из method2data . Так как у нас мог бы быть код как

for (int i = 0; i < n; i++)
  for (int j = 0; j < n; j++)
    for (int k = 0; k < n; k++) {
      addBlock(0,...);
      addBlock(m,...);
    }

мы вызываем addBlock много времени. К сожалению, после некоторого постоянного времени работы над нашим кластером, программа просто перестает работать. Это все еще выглядит как процесс, но не требует никакого процессора. Я обнаружил, что если я удаляю код, который берет что-то из method2data , то все в порядке. Итак, я думаю, что есть некоторые проблемы с доступом к Hashtable. У кого-нибудь есть хорошие идеи?

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

Ответы [ 5 ]

3 голосов
/ 13 июля 2010

Хеш-таблицы в Java могут вызывать неприятное поведение в GC, особенно когда они долговечные и большие.То же самое верно для HashMap.Чтобы выяснить, так ли это для вас, проверьте, сколько ЦП требует процесс.Если ему нужно много ЦП, значит, ГХ работает.Если ему не нужен процессор (просто зависает), значит, у вас есть тупик.

Чтобы найти причину тупика, создайте дамп потока и проанализируйте его.Если вы используете Eclipse, вы можете посмотреть на Lockness .

3 голосов
/ 13 июля 2010

Просто случайная мысль: Возможно, вам не хватило памяти?

Попробуйте запустить приложение с -Xmx512m, чтобы выделить 512 МБ кучи.

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

3 голосов
/ 13 июля 2010

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

[Update] Как справедливо указано @finnw, даже если ConcurrentHashMap кажется , чтобы помочь, вы не можете быть уверены, что основная причина действительно решена.Требуется тщательный анализ и тестирование, чтобы увидеть, действительно ли ваш код является поточно-ориентированным.Не видя код в addBlock(), мы не можем сделать вывод об этом. [/ Update]

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

1 голос
/ 13 июля 2010

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

Как и в стороне, вы используете Vector s в этой HashMap.Векторы синхронизированы и, следовательно, несколько медленнее, чем, скажем, ArrayList с.Возможно, вы могли бы немного снизить производительность, изменив это.

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

0 голосов
/ 13 июля 2010

Это похоже на тупик.Попробуйте переключиться с Hashtable на ConcurrentHashMap или исследовать свое приложение и добавить дополнительные блокировки для устранения взаимоблокировок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...