Получение среднего размера указанного c класса из работающей JVM - PullRequest
1 голос
/ 16 февраля 2020

Я пытаюсь получить средний размер всех экземпляров определенного класса в работающей JVM. Я могу создать дамп кучи с помощью jcmd или аналогичного, но это занимает несколько секунд, и это рабочий сервер, поэтому я бы предпочел что-то быстрее. У jcmd есть возможность создать гистограмму этого формата:

 num     #instances         #bytes  class name
----------------------------------------------
   1:         84907      559415720  [I
   2:       9572537      229740888  java.lang.String
   3:        803323      142900392  [C
   4:       3190710      102102720  java.util.Hashtable$Entry

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

Мне известен метод GDB, но он не подходит, потому что последовательность команд займет у меня несколько секунд для ввода и это примерно время, когда дамп кучи заберет меня с помощью jcmd.

1 Ответ

1 голос
/ 16 февраля 2020

Я не думаю, что универсальный c инструмент, который будет сообщать гистограмму "глубоких размеров" объектов, технически осуществим.

Почему бы и нет?

Если "глубокий" Размер объекта зависит от семантики его класса, у нас проблема в том, что инструмент общего назначения не знает, где находятся границы объекта. Можно реализовать инструмент с жестко закодированными знаниями стандартных типов, таких как String, StringBuffer или HashMap. Однако:

  • Этот подход не масштабируется и не имеет отношения к приложению и сторонним классам библиотек.
  • С некоторыми типами (например, типами коллекций) Граница semanti c (то есть то, что пользователь хочет выяснить) может зависеть от контекста.

В качестве альтернативы, если «глубокий размер» объекта представляет собой просто сумму размеров всех Для объектов, которые достижимы из него, есть две проблемы:

  • Будет существенный перерасчет. Например, большая часть использования памяти для строк находится в символьных массивах. Эти массивы будут учитываться дважды: один раз на графиках достижимости String объектов и второй раз как символьные массивы. Для сложных объектов перерасчет может сделать меру бесполезной.

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

  • Альтернативой было бы избежать двойного счета, не включая "внутренние" объекты в число экземпляров. К сожалению, тогда у вас будет такой же вводящий в заблуждение феномен, что (например) внутренние строки, коллекции и т. Д. c внутри более сложных объектов исчезают. Это означает, что вы больше не можете получать точные оценки их средних размеров.

Я не думаю, что существует схема подсчета, которая действительно будет работать.


Сказав это, исходный код для (OpenJDK) инструментов, которые вы используете в настоящее время, доступен для скачивания. Вы можете модифицировать инструменты для различного анализа размеров объектов. Но я не думаю, что он будет «быстрым» с точки зрения усилий разработчиков или скорости модифицированных инструментов.

...