Измерение и мониторинг размера большого HashMap - PullRequest
3 голосов
/ 15 мая 2019

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

Фон:

В нашей системе имеется несколько хранилищ в памяти (ConcurrentHashMap's), в которых хранятся объекты размером 1–200 тыс. Различных типов.Мы хотели бы периодически отслеживать объем занимаемой ими памяти.

Ограничения / ожидания:

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

С учетом следующих параметров:

Есть поток, который сообщает об использовании памяти # для каждого хэш-карты с помощью:

  1. Измерение размера объектатипа X, используя что-то вроде classmexer и умножьте его на размер hashmap.Это игнорирует память, используемую самим hashmap, предполагая, что она относительно мала по сравнению с ее содержимым.
  2. Создайте еще одну хэш-карту, затем добавьте N объектов этого типа, измерьте ее размер, затем экстраполируйте число, чтобы приблизить его к полному размеру.
  3. Внешне измерьте, а затем подайте это на карту.Думая о jmap или подобном, но не будет ли это очень тяжелой операцией, поскольку она измеряет все в jvm?
  4. Возьмите дельту в размере кучи, когда мы добавляем объекты в хэш-карту.Не уверен, что это возможно, так как он многопоточный
  5. Какой-нибудь другой замечательный вариант?

Ответы [ 2 ]

2 голосов
/ 15 мая 2019

Прежде всего, есть эта замечательная статья Алексея Шипилева (бывший инженер JVM в Oracle, теперь в Redhat), в которой объясняется, что это не так просто .

Каждый объект в Java имеет два заголовка, их размеры могут зависеть от платформы или конфигурации, с которой запускается jvm (UseCompressedOops).

Затем происходит заполнение и выравнивание между полями.и Объекты сами по себе (выравнивание 8 байтов).Кроме того, есть место, которое JVM просто не показывает, потому что оно не может или нуждается в этом.

Все эти вещи делают довольно нетривиальным вычисление размера, который будет иметь определенный Объект в куче;к счастью, JOL существует.У него даже есть много сэмплов ... Вот один маленький пример, предположим, у вас есть такой класс:

static class MyValue {

    private final int left;
    private final String right;

    public MyValue(int left, String right) {
        this.left = left;
        this.right = right;
    }
}

И вы создаете HashMap:

    Map<String, MyValue> map = new HashMap<>();
    System.out.println("empty map = " + GraphLayout.parseInstance(map).totalSize());

    MyValue one = new MyValue(1, "one");
    System.out.println("one = " + GraphLayout.parseInstance(one).totalSize());

    map.put("one", one);
    System.out.println("map after one = " + GraphLayout.parseInstance(map).totalSize());

    MyValue two = new MyValue(1, "two");
    map.put("two", two);
    System.out.println("map after two = " + 
    GraphLayout.parseInstance(map).totalSize());
1 голос
/ 15 мая 2019

Если мое понимание верно, вы хотите знать размер одновременного HashMap.Я думаю, что следующие шаги могут помочь.

  1. Создание фонового потока (не переднего плана).
  2. Сериализация параллельного HashMap с помощью ByteArrayOutputStream.
  3. Получение байтового массиваиспользуя toByteArray ().
  4. Окончательно вычислите размер в КБ / МБ.
  5. Записывайте размер с помощью Logger.

Другой вариант - использовать профилировщик, такой как JProfiler, чтобы увидетьграф объекта и его размер.

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