Использование параллельной хэш-карты для уменьшения использования памяти с помощью пула потоков?

Я работаю с программой, которая выполняет длинные SQL-запросы и сохраняет обработанные результаты в HashMap. В настоящее время, чтобы обойти медленное время выполнения каждого из 20-200 запросов, я использую фиксированный пул потоков и настраиваемый вызываемый объект для поиска. В результате каждый вызываемый объект создает локальную копию данных, которые затем возвращаются в основную программу для включения в отчет.

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

Могу ли я улучшить использование памяти, заменив callables runnables, которые вместо сохранения данных записывают их в параллельный HashMap? Или это звучит так, будто у меня другая проблема?


person William Grobman    schedule 31.08.2011    source источник
comment
Я думаю, что, возможно, я нашел более простой способ сократить его для начала, но я все еще очень заинтересован в дальнейшей оптимизации, как я описал выше. Я заметил, что когда я пишу отчет, мой модуль записи xml создает файл с другой копией карты. Удалив записи карты по мере их записи в файл, я смогу уменьшить еще немного. Интересно, как такие мелочи могут проскользнуть мимо.   -  person William Grobman    schedule 31.08.2011


Ответы (3)


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

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

person Victor Sorokin    schedule 31.08.2011
comment
Я согласен. @William не говорит, почему его пользовательский Callable возвращает копию извлеченных данных, но это кажется довольно странным. - person toto2; 31.08.2011
comment
Синхронизация не требуется, так как он использует Callable. - person toto2; 31.08.2011

Вам действительно нужны все 100-200 отчетов одновременно?

Возможно, стоит ограничить 1-й уровень кэширования всего 50 отчетами и ввести 2-й уровень на основе WeakHashMap? Когда 1-й уровень превышает свой размер, LRU будет перемещен на 2-й уровень, который будет зависеть от объема доступной памяти (с использованием WeakHashMap).

Затем для поиска отчетов вам сначала нужно будет запросить 1-й уровень, если значения нет, запросить 2-й уровень, а если значения нет, то отчет был восстановлен сборщиком мусора, когда не хватило памяти, и вам нужно снова запросить БД для этого отчета. .

person Andrey Taptunov    schedule 31.08.2011
comment
+1 за то, что познакомил меня с другой структурой данных, которая может быть полезна. Я не думаю, что это сработает для этого проекта. - person William Grobman; 31.08.2011

Зависят ли результаты запросов от результатов других запросов? Если нет, всякий раз, когда вы обнаруживаете результаты в другом потоке, просто используйте ConcurrentHashMap, как вы подразумеваете. Вам действительно нужно спрашивать, не приводит ли создание нескольких ненужных копий данных к нехватке памяти в вашей программе? Это должно быть почти очевидно.

person GreenieMeanie    schedule 31.08.2011