Куча Java VisualVM увеличивается для фиктивного приложения [duplicate]

Архитектура

Назначение значений по умолчанию в вызове функции - это запах кода.

def a(b=[]):
    pass

Это сигнатура функции, которая не подходит. Не только из-за проблем, описанных в других ответах. Я не буду вдаваться в это.

Эта функция направлена ​​на то, чтобы сделать две вещи. Создайте новый список и выполните функциональность, скорее всего, в указанном списке.

Функции, которые делают две вещи, являются плохими функциями, поскольку мы учимся на чистых практиках кода.

Атака на эту проблему с полиморфизмом мы будем расширять список python или переносить его в класс, а затем выполнять свою функцию на нем.

Но подождите, пока вы скажете, мне нравятся мои однострочные.

Ну , Угадай, что. Код - это не просто способ управления поведением оборудования. Это способ:

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

Не оставляйте бомбы замедленного действия для себя

Отделяя эту функцию от двух вещей, которые она делает, нам нужен класс

class ListNeedsFives(object):
    def __init__(self, b=None):
        if b is None:
            b = []
        self.b = b

    def foo():
        self.b.append(5)

Выполнено

a = ListNeedsFives()
a.foo()
a.b

И почему это лучше, чем слияние всего вышеописанного кода с одной функцией.

def dontdothis(b=None):
    if b is None:
        b = []
    b.append(5)
    return b

Почему бы не сделать это?

Если вы не сработаете в своем проекте, ваш код будет жить. Скорее всего, ваша функция будет делать больше, чем это. Правильный способ создания поддерживаемого кода состоит в том, чтобы разделить код на атомные части с должным образом ограниченным объемом.

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

Метод foo() не возвращает список, почему бы и нет?

При возврате отдельного списка вы можете предположить, что безопасно делать то, что вам хочется. Но это может быть не так, поскольку он также разделяется объектом a. Заставляя пользователя ссылаться на него как a.b, он напоминает, где находится список. Любой новый код, который хочет изменить a.b, естественно, будет помещен в класс, где он принадлежит.

Функция подписи def dontdothis(b=None): не имеет ни одного из этих преимуществ.

17
задан skaffman 28 August 2011 в 12:40
поделиться

4 ответа

Пильный рисунок в использовании кучи можно объяснить тем, что при вызове вызова System.out.println создается несколько локальных переменных. В частности, в Oracle / Sun JRE несколько экземпляров HeapCharBuffer создаются в молодом поколении, как указано в следующем снимке, полученном с использованием профилировщика памяти VisualVM:

Visual VM - Memory snapshot [/g0]

Интересный бит находится в количестве живых объектов, которые присутствуют в куче. Пилообразный рисунок получается из цикла сбора мусора молодого поколения, который возникает, когда пространство эден заполняется; поскольку в программе нет тяжелой вычислительной активности, JVM может выполнять несколько итераций цикла, в результате чего заполняется пространство eden (размером 4 МБ). Последующий цикл сбора молодого поколения затем очищает большую часть мусора; это почти всегда все пространство eden, если только объекты еще не используются, о чем свидетельствует следующая следа gc, полученная из VisualVM:

Visual VM GC probes [/g1]

Таким образом, поведение пилообразного шаблона может быть объяснено серией распределений объектов в быстрой последовательности, которые заполняют пространство эден, вызывая цикл сбора мусора молодого поколения; этот процесс циклически повторяется без задержек, поскольку основной процесс JVM не вытесняется другим процессом, а основной поток в JVM, который отвечает за распределение объектов, также не вытесняется другим потоком.

23
ответ дан Vineet Reynolds 21 August 2018 в 15:02
поделиться
  • 1
    Получил смысл !!! Спасибо. – buch11 30 August 2011 в 03:20
  • 2
    Пожалуйста. Кстати, я не получал идеальных пилообразных волн, так как я продолжал Alt-tabbing между VisualVM и Eclipse. С другой стороны, ваш скриншот указывает на то, что вы уже некоторое время запускали VisualVM. – Vineet Reynolds 30 August 2011 в 03:22
  • 3
    на самом деле я программировал что-то, что использует потоки, внезапно код перешел в бесконечное loo, я отправился в JVisualVM, чтобы проверить, какие из потоков работают / спать / ждут., и пилообразный передо мной перешел, сразу я подумал это было связано с потоками, но затем попытался запустить код выше, и все головоломки начали оттуда только ... так что мой VisualVM работал все время. – buch11 30 August 2011 в 03:30

Есть много мест, из которых он может исходить, и это, вероятно, зависит от реализации. По крайней мере, возможны следующие (но все это просто спекуляция)

  • где-то в стеке потоков под System.out.println имеется распределение байтового массива (учитывая, что один из основных методов выходной поток - запись (байты [] b, int off, int len))
  • это служебные данные, используемые используемым программным обеспечением мониторинга (я его не использовал)
  • это накладные расходы в netbeans VM, где он заканчивает показывать выход
1
ответ дан Burleigh Bear 21 August 2018 в 15:02
поделиться

Любой процесс, распределяющий объекты с регулярной скоростью, приведет к устойчивому увеличению потребления памяти кучи, а затем мгновенным падениям, когда сборщик мусора собирает ненужные объекты, что приводит к тому, что пилообразная форма.

In в случае, если вы задаетесь вопросом, почему ваш Java-процесс сохраняет память распределения при записи на System.out, имейте в виду, что другие потоки (например, одна из которых загружает текущую статистику памяти в JVisualVM) могут быть теми, которые выделяют память.

5
ответ дан meriton 21 August 2018 в 15:02
поделиться

Фактически jVisualVM вызывает дополнительное выделение объектов. jVisualVM и jconsole используют расширения Java Management Extensions. Прикрепление к запущенному приложению и запрос JVM-метрик, вызывающих создание дополнительных объектов. Вы можете проверить это, добавив к вашему программному вызову

Runtime.getRuntime().freeMemory() 

, который сообщает о свободной памяти в куче JVM. Он покажет [почти] отсутствие изменения памяти, запустив ваш код, но как только вы подключите jVisualVM к вашей программе, вы увидите увеличение использования памяти.

1
ответ дан ozzo 21 August 2018 в 15:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: