Работа с огромными списками массивов, Java OutOfMemoryError: пространство кучи Java использует базу данных?

У меня проблема с памятью, причину которой я полностью понимаю, но не знаю, как ее исправить. Я попытался использовать тег -Xmx2g и увеличить размер кучи, но, похоже, существует скрытый максимум. (если я использовал -Xmx512m, у меня одновременно закончилось место).

Предположим, у меня есть 2 объекта, область и пользователь. Объект My Area содержит список пользователей ArrayList:

public class Area {
      int numUsers;
      ArrayList<User> userList;
}

Мой класс User содержит ArrayList друзей:

public class User {
      int userID;
      int numFriends;
      ArrayList<User> friends;
}

Просто используя одну область с 1 миллионом пользователей и в среднем 200 друзьями на пользователя, я исчерпал место в куче после того, как было создано около 680 000 пользователей. Очевидно, что если я уменьшу среднее количество друзей/пользователей до значения, близкого к 100, я смогу хранить все эти объекты в куче.

Что, если я хочу смоделировать 2 миллиона пользователей в области? Или сотни областей?

Является ли база данных единственным возможным способом моделирования с использованием этой информации при таком большом количестве данных?


person Eddie    schedule 11.01.2011    source источник
comment
Да, поместить граф такого размера в одну виртуальную машину будет тесно. И нет, помимо реляционной базы данных существует множество других способов хранения и работы с таким объемом данных. Какой способ подходит в вашем случае, зависит от того, что вы хотите делать с данными, и каковы ваши требования к производительности. Возможно, вы даже можете создавать данные по мере необходимости, избегая необходимости хранить их целиком?   -  person meriton    schedule 11.01.2011
comment
Необходимость хранить его полностью заключается в том, чтобы в конечном итоге иметь несколько областей, в которых некоторые пользователи из области 1 могут иметь друга из области 42. Я полагаю, что хранение его в памяти не будет вариантом в этот момент. На данный момент мне просто нужно смоделировать эту информацию. Проект требует реалистичной модели социальной сети. Какие-нибудь структуры, которые я должен исследовать, о которых вы знаете?   -  person Eddie    schedule 11.01.2011
comment
Хранение в памяти может зайти очень далеко. С текущими ценами на память в 100 евро/8 ГБ большинство систем не должны основываться на дисках.   -  person Stephan Eggermont    schedule 12.01.2011


Ответы (3)


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

person Stephan Eggermont    schedule 11.01.2011
comment
Хм... есть ссылки на структуры, о которых вы говорите? Огромное спасибо. - person Eddie; 11.01.2011
comment
Просто добавить класс FullyConnectedSubset, содержащий ArrayList пользователей, и сделать друзей полиморфными? - person Stephan Eggermont; 12.01.2011
comment
Я не совсем уверен, что вы имеете в виду. Я полагаю, вы говорите об уровне друзей. Таким образом, пользователь со 100 друзьями будет связан с каждым из этих друзей, но это не поможет мне уместить это в памяти. И было бы лучше, чтобы Друг расширил Пользователя? Не уверен, как это сэкономит место, так как сейчас Друг является пользователем. ArrayList‹Пользователь› друзей; - person Eddie; 12.01.2011
comment
В полностью связанном подмножестве каждый друг связан друг с другом. Вместо того, чтобы хранить это как список n-1 записей в n друзьях, создайте один специальный элемент: FullyConnectedSubset, который вы добавите к этим n друзьям. Взяв O (n) вместо O (n ^ 2) пространства. Затем вам нужно создать некоторые средства доступа/итераторы, чтобы скрыть эту деталь реализации. - person Stephan Eggermont; 14.01.2011

Вы можете, конечно, запустить более 2 м на 64-битной Java, но это не решит проблему. Кстати, для области вам, вероятно, понадобится идентификатор (а не numUsers), количество пользователей/друзей можно получить из list.size()

Хранилище базы данных/диска — это естественное решение для представления большого количества объектов, в качестве альтернативы вы можете использовать кластер серверов (помимо запуска огромной коробки с 500+ ГБ памяти)

Чтобы ответить на вопрос, вам нужно предоставить еще некоторые данные: в чем смысл областей/френд-графов/и т. д.


Если вы можете закодировать свою собственную структуру (ure), используя ByteBuffer (что, вероятно, непростая задача), вы можете выйти за пределы 32-битных ограничений с помощью java.io.MappedByteBuffer, ScatteringByteChannel/GatheringByteChannel. Тем не менее, это в любом случае задача не для новичков, но если вам нравится программирование, я бы посоветовал попробовать свои силы.

Желаю тебе удачи в учебе.

person bestsss    schedule 11.01.2011
comment
Количество пользователей фактически передается в область до ее создания. Таким образом, когда я создаю несколько областей с разным количеством пользователей, я могу это сделать. и у каждого пользователя будет свой идентификатор. Это школьный проект по созданию реалистичной модели социальной сети. - person Eddie; 11.01.2011
comment
В вашей графовой модели есть серьезный недостаток: в ней не будет какого-либо реалистичного метода поиска/трассировки, если вы полагаетесь на ArrayList. ArrayList требует O(n) для простой операции contains. Несколько других замечаний: убедитесь, что у вас есть только 1 экземпляр пользователя на объект (я предполагаю, что идентификатор пользователя определяет личность) - person bestsss; 12.01.2011
comment
Вызовите trimToSize() или убедитесь, что вы используете конструктор с initialCapacity, чтобы избежать избыточных байтов в Object[]. _____ Итог: если вам нужна большая память, используйте 64-битную ОС - person bestsss; 12.01.2011
comment
Я знаю, что структура не будет эффективна при реалистичном моделировании. Я надеялся создать данные в памяти, а затем сбросить их в более подходящую структуру для моделирования. Хотя это выходит за рамки проекта. - person Eddie; 12.01.2011
comment
Создание его во внешней форме (поскольку вам нужно выставить свою структуру, если вы все равно хотите, чтобы ее использовали по-настоящему) может сделать это. (Говоря о MappedByteBuffer) - person bestsss; 12.01.2011
comment
К сожалению, такой проект будет на 95% управлять структурой, чем делать что-то действительно полезное :) - person bestsss; 12.01.2011
comment
Под внешней формой вы имеете в виду не в памяти jvm правильно? Хотел бы я просто использовать все свои 4 ГБ памяти, и это даже не было бы проблемой ... - person Eddie; 12.01.2011

Чтобы получить доступ к большему объему динамической памяти, перейдите на 64-разрядную ОС и 64-разрядную JVM. Если у вас возникают проблемы с -Xmx512m, вы используете 32-битную ОС и/или JVM.

person Konstantin Komissarchik    schedule 11.01.2011
comment
Я использую Fedora c14 32 бит. У меня максимум 256? - person Eddie; 11.01.2011
comment
Фактический максимум зависит от ряда сложных вопросов, таких как отображение памяти библиотек и то, как это фрагментирует пространство памяти. Возможно, вы сможете получить немного больше полезного запаса памяти, убедившись, что запускаете java с использованием исполняемого файла java, а не связанной библиотеки (не уверен, что библиотека называется в Linux). - person Konstantin Komissarchik; 12.01.2011