Произошла ошибка вне памяти при использовании Hashmap для сохранения больших значений - PullRequest
0 голосов
/ 12 марта 2012

У меня есть простой объект:

public class ActVO
{
   private Long     mFromId;
   private Long     mToId;
   private int      mType;
}

Он также был сохранен в базе данных Oracle. В настоящее время в БД хранится около 1 миллиона строк. Я хочу прочитать все эти строки в память и кэшировать в HashMap, используя ключ mFromId.

Моя проблема в том, что произошла ошибка памяти при чтении до 400 тысяч строк (память запуска была выделена для 1G). Я использовал cern.colt.map.OpenLongObjectHashMap и sun HasHmap, оба столкнулись с одной и той же проблемой.

Кто-нибудь может сказать, какой 3-й API карты или другой способ может избежать этой проблемы?

Ответы [ 2 ]

2 голосов
/ 12 марта 2012

Будет невозможно сохранить столько объектов, которые не умещаются в доступной памяти. Есть два решения. Во-первых, это использовать кеш, который будет сохраняться в локальных файловых объектах, которые не помещаются в памяти. Что-то вроде ehcache . Второе решение вместо использования объектов для переключения на двумерный массив

long[][] cache = new long[1000*1000][];
long[] row = new long[2];

row будет содержать mToId и mType. Строки будут вставлены в cache с использованием mFromId в качестве индекса.

Вот пример:

Random r = new Random();

class ActVO {

  private long mFromId;
  private long mToId;
  private int mType;
}

int capacity = 1000*1000;
List<ActVO> resultSet = new ArrayList<ActVO>();
for (int i = 0; i < capacity; i++) {
  ActVO element = new ActVO();
  element.mFromId = i;
  element.mToId = r.nextLong();
  // let's say there are not more than 10 types
  element.mType = r.nextInt(10);
  resultSet.add(element);

  if (i == 57) {
    System.out.printf("       db result 57: mToId=%d, mType=%d\n", element.mToId, element.mType);
  }
}

long[][] cache = new long[capacity][];

// iterating trough a database set
for (ActVO element : resultSet) {
  long[] row = new long[2];
  row[0] = element.mToId;
  row[1] = element.mType;
  cache[(int) element.mFromId] = row;
}

System.out.printf("57th row from cache: mToId=%d, mType=%d\n", cache[57][0], cache[57][1]);
0 голосов
/ 12 марта 2012

Мои предложения будут;

  • не используйте Long, если хотите использовать long. Может быть в 5 раз больше в памяти.
  • Я бы посоветовал вам использовать TLongObjectHashMap, который сделает хранение ключей более эффективным.

Это будет использовать около 64 байтов на запись. Если вам нужна более компактная форма, вы можете сделать это, но с возрастающей сложностью. Вы не будете делать лучше, чем 20 байтов на запись.

...