@daniil14056

Как при сборки мусора и перемещении объекта, сохраняется корректность ссылок?

Я чет-то не могу найти, каким образом сохраняется корректность ссылок.
Везде где читаю, этот момент пропускается
int[]arr=new[100000000000000000000000000000000000000000]
 arr1=arr;
arr2=arr;
arr3=arr;
....  триллион раз и триллион кода

Теперь где-то, сборщик мусора, начинает переносить arr в другое место.
Вопрос, как об этом узнают другие ссылки?
Тут 2 способа на ум сразу.
Первый, типа взять, и каждому указателю обновить значения. Долго.
Второй. Сделать, промежуточный массив, который будет хранить адреса объектов. А любая ссылка, и любое разыменование объекта, будет проходить, через этот массив, как двойной указатель **. И когда объект перемещается, то обновляется его адрес в этом массиве.
Тогда итог, что языки с сборщиком мусора, под в 2 раза медленнее должны быть.(помимо сборки) Или есть какой еще способ.

А еще не понимаю. Каким образом достижимость объектов определяется, без пасты, где точка входа. Читал что проверяется все начиная со стека и регистров. Но на стеке лежат числа.а в регистрах тем более, могут быть как числами, так и адресами, как и числами, случайно совпавшими с адресами, и как типа определить это значения на стеке адрес или значение, только как границы региона мерить, и то может быть случайное число в границы памяти попадет., и будет как адрес обработано.
  • Вопрос задан
  • 156 просмотров
Решения вопроса 5
AshBlade
@AshBlade Куратор тега C#
Просто хочу быть счастливым
Управление памятью в .NET для профессионалов

Как работает сборка мусора.
В .NET используется 2 фазная сборка мусора: Mark & Sweep (Пометить и Убрать).

Mark

На этом этапе обходится весь граф объектов. И выявляются все недостижимые.

Каким образом достижимость объектов определяется?

Достижимые это:
- Аллоцированные на стеке
- В статических полях
- Достижимые из достижимых (см. выше)

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

Но на стеке лежат числа. могут быть как числами, так и адресами, как и числами?

JIT копилятор достаточно умный, чтобы сгенерить код, который будет знать, что за объект/ссылка лежит на стеке. Так и получаются знания об объектах.

Sweep

Тогда итог, что языки с сборщиком мусора, под в 2 раза медленнее должны быть.(помимо сборки)

Вот тут интереснее. Есть несколько хаков как достигается большая производительность.
1. Линеризованное пространство памяти.
Адреса 0, 1 и 2 поколения расположены не абы где, а последовательно, друг за другом. Т.е. если нужно сократить пространство 0 поколения, то это означает простое передвигание указателя влево.

2. Переход в след. поколение происходит не всегда
Из 0 в 1 - переход быстрый, но из 1 в 2 - не всегда.
На этом этапе тоже может не затрачиваться много времени.

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

Теперь где-то, сборщик мусора, начинает переносить arr в другое место.

Ты слишком большой массив выделил, он аллоцируется в LOH. Оттуда не вытащишь.

Я много о чем не упомянул. Например, очередь финализации, таблица дескрипторов (Handle), сегментирование памяти и т.д. но ответы на основные вопросы дал
Ответ написан
yarosroman
@yarosroman Куратор тега C#
C# the best
Там выше посоветовали книгу Конрада Кокосы, добавлю от себя книгу Саши Гольдштейна и у Станислава Сидристого есть недописанная книга. Еще на ютубе с dotNext`а можно посмотреть, что то было интересного про внутненности dotnet`а.
Ответ написан
Комментировать
mayton2019
@mayton2019
Bigdata Engineer
Нету никаких указателей. Указатели - это терминология С++.

Да GC обладает правом двигать объекты в памяти. Но это тебя не должно волновать.
Ты работаешь в прарадигме managed memory.

Тость НИКАКОЙ АДРЕСНОЙ арифметики ты не имеешь права использовать.
Используй ссылки объекты и все будет норм.
Ответ написан
vabka
@vabka Куратор тега .NET
Токсичный шарпист
Если ты не используешь unsafe, то сборщик мусора сам все ссылки после передвижения поправит - ради этого он все managed потоки останавливает.

Если ты используешь unsafe и передаёшь куда-то сырые указатели, то тогда тебе надо запинить объект чтобы гарантировать, что объект не будет перемещаться. Для этого, например, есть конструкция fixed, но оно работает только в рамках блока и одного потока.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы