Какие механизмы языка C# используются для передачи экземпляра объекта в метод `G C .AddMemoryPressure`? - PullRequest
1 голос
/ 26 февраля 2020

Какие механизмы языка C# используются для передачи экземпляра объекта методу GC.AddMemoryPressure?

Я встретил следующий пример кода в CLR через C# книга:

private sealed class BigNativeResource {
    private readonly Int32 m_size;
    public BigNativeResource(Int32 size) {
        m_size = size;
        // Make the GC think the object is physically bigger
        if (m_size > 0) GC.AddMemoryPressure(m_size);
        Console.WriteLine("BigNativeResource create.");
    }
    ~BigNativeResource() {
        // Make the GC think the object released more memory
        if (m_size > 0) GC.RemoveMemoryPressure(m_size);
        Console.WriteLine("BigNativeResource destroy.");
    }
 }

Я не могу понять, как мы связываем экземпляр объекта с давлением, которое он добавляет. Я не вижу, чтобы ссылка на объект передавалась в GC.AddMemoryPressure. Связываем ли мы добавленное давление памяти (amp) с объектом вообще?

Кроме того, я не вижу никаких причин в вызове GC.RemoveMemoryPressure(m_size);. Буквально это должно быть бесполезно. Позвольте мне объяснить себя. Есть две возможности: существует связь между экземпляром объекта или нет такой ассоциации.

В первом случае G C теперь должен m_size, чтобы расставить приоритеты и решить, когда провести коллекцию. Таким образом, он определенно должен сам снять нагрузку на память (в противном случае, что бы это значило для G C до remove an object while taking into an account the amp?).

В последнем случае не ясно, какой смысл использовать добавление и вообще снял усилок. G C может работать только с корнями, которые по определению являются экземплярами классов. Т.е. G C может собирать только предметы. Таким образом, в случае отсутствия связи между объектами и усилителем, я не вижу, как усилитель может повлиять на G C (поэтому я предполагаю, что существует ассоциация).

Ответы [ 3 ]

7 голосов
/ 26 февраля 2020

Я не могу понять, как мы связываем экземпляр объекта с давлением, которое он добавляет.

Экземпляр объекта связывает давление, которое он добавляет, со ссылкой на себя, вызывая AddMemoryPressure. Объект уже имеет идентичность с самим собой! Код, который добавляет и снимает давление, знает, что такое this.

Я не вижу, чтобы ссылка на объект передавалась в G C .AddMemoryPressure.

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

Связываем ли мы добавленное давление памяти (ампер) с объектом вообще?

G C этого не делает. Если ваш код делает, это ответственность вашего кода.

Кроме того, я не вижу никаких причин для вызова GC.RemoveMemoryPressure(m_size)

Это так, что G C знает, что дополнительное давление исчезло.

Я не вижу, как усилитель может влиять на G C

Это влияет на G C добавив давление!


Я думаю, что есть фундаментальное неправильное понимание того, что здесь происходит.

Добавление давления памяти просто говорит G C, что существуют факты о распределении памяти, которые вы знаете, и что G C не знает, но имеет отношение к действию G C. Нет требования, чтобы добавленная нагрузка на память была связана с каким-либо экземпляром какого-либо объекта или привязана к времени жизни любого объекта .

Код, который вы разместили, является общим шаблоном: объект имеет дополнительную память, связанную с каждым экземпляром, и он добавляет соответствующее количество давления при выделении дополнительной памяти и удаляет его при освобождении дополнительной памяти. Но не требуется , чтобы дополнительное давление было связано с указанным c объектом или объектами. Если вы добавили кучу неуправляемых выделений памяти в своем методе static void Main(), вы можете решить добавить соответствующее ему давление памяти, но с этим дополнительным давлением нет объекта .

2 голосов
/ 26 февраля 2020

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

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

В документации ясно об этом: когда неуправляемая память уходит, вы должен сообщить сборщику мусора, что он ушел.

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

2 голосов
/ 26 февраля 2020

Эти методы существуют, чтобы G C узнал об использовании памяти вне управляемой кучи. Нет объектов для передачи этим методам, потому что память не связана напрямую с каким-либо конкретным управляемым объектом. Обязанностью автора кода является правильное уведомление G C об изменении использования памяти.

GC.AddMemoryPressure(Int64)

… среда выполнения учитывает только управляемая память, и, следовательно, недооценивает срочность планирования сбора мусора.

Крайний пример: 32-битное приложение, и G C считает, что оно может легко выделить почти 2 ГБ управляемых (C#) объектов. В качестве части кода вы используете встроенное взаимодействие для выделения 1 ГБ. Без вызова AddMemoryPressure G C по-прежнему будет думать, что можно ждать, пока вы не выделите / освободите много управляемых объектов ... но примерно через некоторое время, когда вы выделите 1 ГБ управляемых объектов, G C переходит в странное состояние - оно должен иметь все лишние ГБ для игры, но ничего не осталось, поэтому он должен карабкаться, чтобы собрать память в этот момент. Если бы AddMemoryPressure использовался должным образом, G C имел бы возможность приспособиться и более агрессивно собирать ранее в фоновом режиме или в точках, которые допускали более короткое / меньшее воздействие.

...