Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Сборщики мусора с учетом используемости переменных

В менеджере памяти нет нужды делить служебные данные и переменные. Сделали следующее: для каждой ячейки памяти, которая выделялась, заводили служебные переменные (размер и счётчик – специальная переменная, в которой при выделении памяти с указателем, устанавливалось значение 1 – один указатель на переменную).
B:=A – содержимое А копируется в В, счётчик увеличивается на 1
Если в указатель В записываю константу, В будет переопределено. Переход к ячейке, переход к счётчику, уменьшение на единицу, запись. Если то же самое проделать с А, то счётчик – 0. Переменная не доступна из тела программы никогда (её адреса были стёрты).
Когда в системе началась сборка мусора, сборщик искал 0 счётчики, где 0 – считаются свободными. Если две рядом – они склеиваются. Получаем значительную задержку, нам необходимо прокрутить все эти указатели, нельзя было произвольно обращаться с ячейками памяти, как в фон Неймановской архитектуре. Здесь различается. Нет прямого редактирования памяти. В этих языках над указателями разрешается лишь операция присвоения. Пример: LISP.
В результате при сборке мусора полностью очищается кэш-память, при работе программы добавляется модуль для работы со счётчиками, повышается расход ОЗУ на хранение счётчика.
Возникают новые проблемы:
страницы памяти, которые отвечают за динамическое выделение, находятся или в ОЗУ или на диске, если страница выгружена на диск, я её должен подкачать в память. Какие переменные проверять? Не ясно. Приходится загружать из файла подкачки и начинает лопатить все переменные и искать счётчики. Языки со сборкой мусора зашли в производство в 1990х. Джава-машина несовместима ни с одним чипом. Она имеет аппаратную архитектуру, которая в принципе не реализуема. Имеет Гарвардскую архитектуру.

Каждая переменная имеет указатель и тип в нем. При выполнении операций автоматически идет проверка операций на возможность выполнения. Нельзя обратиться в этой архитектуре к середине ячейки. Каждая машинная команда проверяется аппаратно на процессоре на правильность типов.

В Гарвардской архитектуре можно разрабатывать сложные программы. Современные программы так и разрабатывают. AutoCAD – под.NET, написана на C#. Работа со счётчиком контролируется виртуальной машиной. Джава получила сборку мусора на основе менеджера памяти списочного, поэтому тупило жутко. Когда вышла 2 версия Джавы, они поменяли убогий МП на более сложные интеллектуальные МП.


 

Почему курица с одной ногой?

А у меня была кастрюля маленькая, вторая не влезала.

Почему стек растет вниз?

Лекция 19.02.2013

А на экзамене буду дрючить!

В менеджерах памяти со сборкой мусора указатели на лету больше производить нельзя, арифметику производить нельзя, можно формировать указатель путем new, также оставили присвоение указателей.

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

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

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

Прикол: если арифметики указателей нет, то я получаю доступ к объектам по прямым ссылкам, к массиву по индексам.

ДО

У нас есть указатель, есть объект и объект зафиксирован в пространстве

ПОСЛЕ

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

У нас есть ссылка на объект. Мы думаем, что объект расположен именно тут, но МП скрывает от нас, где физически находится объект. Появилась возможность проводить дефрагментацию памяти. МП такого типа теоретически позволяет уменьшить расход кучи, он дефрагментирован.

Фактически произошло повторение виртуализации памяти, только на низшем уровне.

Но у нас по прежнему есть виртуальные объекты и их несколько. Внутри этих объектов есть поля, которые ссылаются друг на друга. Если объект находится в ВАП на диске, то придется его загрузить, чтобы проверить 0-вой счётчик. Схема со счётчиком оказалась неэффективной.

Решили производить поиск живых среди всех – трассировка маркировкой:
у нас есть некоторое количество ссылок, например переменная в стеке. Можно пройтись по памяти и узнать, где лежат все ссылки (из-за Гарвардской архитектуры). Каждый указатель, который куда-то указывает, указывает на объект. Проходимся по ссылкам, и маркируем объекты, если не него есть ссылка или в нем есть ссылки на другие объекты.

Сборка мусора – дорогостоящая операция. Трассировка – самая медленная операция.

Улучшить эту ситуацию можно. Надо запускать сборщик мусора, когда мы простаиваем. System.gc(). Но тоже плохо. У нас такая плохая ситуация с памятью, что мы готовы пожертвовать производительностью. Вообще в современных языках ручной запуск сборки мусора не приветствуется никогда. Можно использовать, если мы знаем, что сейчас у нас будет огромная пауза. Например, обращение к СУБД, где запрос будет обрабатываться долго.

Трассировка – пока что пик развития МП.

Живые объекты остались, а неживые удалились.

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

Если мы удалили ссылку и на эти два объекта ничего не указывает, то удалятся оба. Отсоединение агрегатов безболезненно. Удаляем верхний узел – удаляется все, что снизу.

Сборщик мусора удаляет объекты из памяти, в результате у нас остаются дырки – свободные места тех объектов, которые были удалены. Как узнать, хватит ли места для нового объекта? Делают дефрагментацию, но опять таки – это лишние затраты производительности.

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

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

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

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

Сборка мусора начинается с молодого поколения. Когда запускается garbage collector, то выполняется ПОЛНАЯ сборка мусора. Автоматически производится сборка мусора настолько эффективно, насколько возможно. По-разному в зависимости от того, какие динамические параметры накоплены.

Как понять нужен ли нам объект? Проходимся по стеку и смотрим, указывают ли указатели на объекты. Для того, чтобы понять, есть ли на этот объект ссылка из старых объектов, нужно протрассировать старые объекты.

А как бы вот этого не делать? (трассировку большого старого поколения ради эффективного выделения памяти в молодом)

1. Разработчики просят программистов не делать ссылки из старых объектов на молодые

2. В тот момент когда присваиваются указатели, объекты получают повышение старости (если я из старого объекта делаю ссылку на молодой, он становится старым)

Происходит копирование старого объекта с изменённым параметром.

В Джава удобнее создавать объект тогда, когда он нам нужен.


 

26.02.2013

Мы отвечаем за программные модули, которые используем. Поэтому нужно следить насколько качественно модуль поддерживает многозадачность и т.д.

Если указатель нам не нужен, то стоит его уничтожить, присвоив ему NULL, чтобы не возникало «ложного запоминания». Но это не значит, что нужно каждый раз присваивать NULL, потому что это может быть лишним.

Нужно тогда, когда мы храним недействительные указатели.

  C/C++ Java
Константы Адреса (прописаны компилятором жёстко) Адрес
Примитив (адрес) Адрес (за нас прописывает компилятор) Адрес
Ссылка Адрес Адрес
Указатель Адрес, который от нас скрывает компилятор, в котором есть адрес -
Объект Структура Адрес, скрываемый компилятором на непосредственно объект** Имя, которое ссылается на ячейку, в которой хранится ссылка на объект*
Массив Скрытый теневой указатель на 1ый элемент  

 

*Над указателями мы могли поменять тип и выполнять арифметику. В Java можно выполнять присвоение.

** struct x y; //объявили ссылка типа структуры и она содержит адрес объекта
(struct x *) y

int a[3];

int *b = malloc(sizeof(int)*3);

a[0] = 1;//массив на стеке

b[0] = 1;//массив на куче

a = b //переприсвоение адресов, будут копироваться значения


Недостатки: можно путаться. Массив созданный на стеке можно передать (его адрес), как будто это массив созданный на куче.

struct x A;

(struct x*) B = malloc (…)

A.internal = 1;

B->internal = 1;

A = B//невозможно, потому что будет копироваться адрес структур

Если объект статически, то «.», если динамически, то «->».

 

Это своего рода объекты и технически должны проходить вот таким же способом (адрес, сам объект). Интересно их поведение на дальнейшей работе. Объект может либо существовать, либо не существовать.

Указатель связан с именем (либо ссылка есть, либо её нет), если ссылка единственная, то объект будет собран сборкой мусора.

<== предыдущая лекция | следующая лекция ==>
Ссылочный менеджер памяти | Phantom Reference
Поделиться с друзьями:


Дата добавления: 2014-01-06; Просмотров: 231; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.007 сек.