HashMap абсолютная емкость - PullRequest
       4

HashMap абсолютная емкость

0 голосов
/ 26 сентября 2011

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

Большое спасибо.

Ответы [ 2 ]

5 голосов
/ 26 сентября 2011

Единственное, о чем я могу думать, это может объяснить проблему, если ваши объекты очень большие и у вас почти не осталось кучи.Когда это происходит, JVM может останавливаться на все более длительный период времени, пытаясь очиститься.В Java 6 он пытается обнаружить это до того, как он станет действительно плохим, и выдает OutOfMemoryError (до того, как он полностью иссякнет, но не смог очистить много) Java 5.0 не делает этого.

Это объясняет, почемувещи снова ускоряются, когда вы отбрасываете несколько объектов.


Стандартная реализация HashMap ограничена примерно 750 миллионами записей (в зависимости от того, как вы ее используете, например, средняя загрузка). Максимальная емкость, которую он может иметьравен 2 ^ 30 (один миллиард) и с коэффициентом загрузки 0,75f (~ 750 м записей) он будет пытаться увеличить базовый массив, чтобы удвоить этот размер, что он не может сделать.(Максимальный размер: Integer.MAX_VALUE)

Вы можете использовать LinkedHashMap в качестве кэша, исключая запись "eldset" на основе правила, которое вы должны предоставить.

Однако, если только не HashMapсинхронизируется не будет блокировать.Если он потерпит неудачу, он выдаст исключение.

Единственный последовательный способ получить Карту для блокирования таким образом - это завести тупик.

Другой способ, которым это может случиться, - это если вы используете одну и ту же карту в двух потоках небезопасным способом.В этом случае поведение не определено, однако я видел, что оно вызывает проблемы в JVM (очень редко) и даже «зависает» в потоке.Даже если бы это было так, я ожидал бы, что это будет иметь место при увеличении HashMap с коэффициентом загрузки по умолчанию, который будет 3072 (т.е. 4096 * 0,75), а не значение, которое вы видите.


Даже плохая реализация hashCode не может объяснить эту проблему.

static class BadHash {
    @Override
    public int hashCode() {
        return 1;
    }
}

public static void main(String... args) {
    Map<BadHash, Boolean> map = new HashMap<BadHash, Boolean>();
    for (int i = 0; i <= 100000; i++) {
        if (i % 10000 == 0) System.out.println(i + ": " + new Date());
        map.put(new BadHash(), true);
    }
}

печатает следующее через 14 секунд.

0: Mon Sep 26 12:23:39 BST 2011
10000: Mon Sep 26 12:23:39 BST 2011
20000: Mon Sep 26 12:23:39 BST 2011
30000: Mon Sep 26 12:23:40 BST 2011
40000: Mon Sep 26 12:23:41 BST 2011
50000: Mon Sep 26 12:23:42 BST 2011
60000: Mon Sep 26 12:23:44 BST 2011
70000: Mon Sep 26 12:23:46 BST 2011
80000: Mon Sep 26 12:23:48 BST 2011
90000: Mon Sep 26 12:23:51 BST 2011
100000: Mon Sep 26 12:23:53 BST 2011
4 голосов
/ 26 сентября 2011

Запустите эту программу (в основном классе):

Map<Long, String> map = new HashMap<Long, String>();
for (long l = 0L; l < 100000; l++) {
    map.put(Long.valueOf(l), String.valueOf(l));
}
System.out.println(map.size());

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

HashMap может поддерживать много элементов, если алгоритм hashCode() хорош. Очевидно, у тебя плохо.

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