* создать предопределённый метод очистки по образцу Finalize
* сделать возможность вызова процедур через рефлексию, подобно PechPoAdr:
проц PechPoAdr*(w: Потоки.Писарь; xAddress, typeDescAddress : адресВПамяти);
* сделать метод "вызови процедуру для каждой ненулевой ссылки", а процедура будет из прошлого пункта - хотя бы для объектов
* куда-то нужно прилепить инфу о том, что данный объект подлежит подсчёту ссылок - к типу объекта, к экземпляру или к указателю (разбор ниже)
* поменять копирование объекта и его удаление, чтобы вызывался этот метод
Куда прилепить инфу о подсчёте ссылок?
* нельзя прилепить к указателю на экземпляр, т.к. либо все указатели на данный экземпляр нужно считать, либо ни одного
* можно ли прилепить к экземпляру? Если это запись в куче, то у ней есть свой кусок памяти, у него есть заголовок, в нём можно разместить бит, монитор, возраст и кво ссылок. Если это запись в массиве, то на неё нельзя получить указатель, ухаха. Если она живёт на стеке или передана как var параметр, то её жизнеспособность защищена самим стеком, указатель на неё получить нельзя и считать ничего не надо. Таким образом, функция обработки ссылки при копировании может сходить по указателям и посмотреть, не нужно ли поменять ссылки.
* можно ли прилепить к типу записи? Тогда это по сути дела параметрический тип, и возникнет расщепление генеалогии, что не есть хорошо. Ведь указатель на обычную и мусоросборную записи будут несовместимы по присваиванию. Или будут?
подсчёт ссылок
Re: подсчёт ссылок
Промежуточные итоги мимимизации задачи. Вводим понятие "считаемого" (RC) и "сметаемого" (GC) объектов.
- помним цель создания считаемых объектов: внедрение баз данных в памяти. Это - гораздо проще, чем "произвольный граф объектов"
- будут сильные и слабые указатели. Слабые нужны для указания на хозяина.
- очистка объекта управляется счётчиком сильных указателей, удаление из памяти - суммой сильных и слабых.
- с утечками памяти через циклы на уровне ЯП не боремся
- для борьбы с ними создадим динамический инструмент, ищущий мусор (стандартная практика)
- избежим ли отдельной иерархия типов для считаемых (RC) и сметаемых (GC) контейнеров
- могут ли считаемые объекты ссылаться на сметаемые?
- могут ли сметаемые объекты ссылаться на считаемые?
- насколько прозрачны в языке будут обёртки для считаемости?
- что делать с тредами?
Последний раз редактировалось БудДен 08.08.22 14:01, всего редактировалось 3 раза.
Re: подсчёт ссылок
Лис, не мешай работать.
Re: подсчёт ссылок
Вариант решения недорешённого:
- все считаемые объекты живут в одной-единственной активности (на одну библиотеку хватит)
- ссылки между считаемыми и сметаемыми объектами осуществляются через спец.адаптеры, в т.ч. понадобится невладеющий (построенный на слабых считаемых ссылках) контейнер (список) ссылок со считаемых на сметаемые. То же в обратную сторону - потребуются финалайзеры для ссылок с сметаемых на считаемые.
- создание ссылки с сметаемого на считаемый под капотом обменивается сообщением с тредом считаемых объектов
- при остановке мира на сборку мусора тред считаемых тоже замирает
- примитивы новСчит, новСмет, а также ЯАктивностьСчитаемыхОбъектовЛи?
нов = если3(ЯАктивностьСчитаемыхОбъектовЛи?, новСчит, новСмет)
Последний раз редактировалось БудДен 08.08.22 14:02, всего редактировалось 3 раза.
Re: подсчёт ссылок
В общем, пока основная заминка - с синхронизацией операций. Всё видится каким-то ущербным. Можно блокировать объект-цель ссылки, при копировании ссылки на него. Это слишком медленно и вдруг он уже будет на тот момент заблокирован чем-то? Либо сделать отдельный монитор именно для подсчёта ссылок, тогда чуть лучше, но для каждого объекта нужен отдельный монитор - слишком жирно. Либо сделать глобальную блокировку, например, использовать блокировку "ЯдернаяБлокировкаДляРаботыСКучей" - она запрашивается на каждое выделение динамической памяти. Есть также более приоритетная (наверное) ЯдернаяБлокировкаДляРаботыСПамятью.
Вторая проблема - как распределять выделения памяти между сметаемыми и считаемыми кучами - тут нужно попробовать примеры.
Вторая проблема - как распределять выделения памяти между сметаемыми и считаемыми кучами - тут нужно попробовать примеры.
Последний раз редактировалось БудДен 08.08.22 14:01, всего редактировалось 1 раз.
Re: подсчёт ссылок
Нам нужно будет вставить свой код в копирование записи и массива, поскольку в этих случаях может понадобиться менять счётчики ссылок. Посмотрим, что у нас есть на эту тему. Ищем слово Assign в LisIntermediateBackend.
Здесь всё ясно - при генерации кода для предписания (statement), присваивание значения вызывает процедуру Assign (кстати, не пришло ли время перевести этот модуль?)
Код: Выделить всё
...
| SyntaxTree.ПредписаниеПрисвоитьЗначение делай Assign(x.куда, x.что );
...
кон Statement;
Re: подсчёт ссылок
Нашёл опцию платформы --writeBarriers, которая включена в сборках для Lin и Win, но выключена в сборке Bios. Если опция включена, то при копировании указателя или записи вызывается Heaps.MarkPointer и Heaps.MarkRecord. В чём суть этой опции - пока неясно, но сама по себе опция хороша тем, что (наверное) встроена во все интересные нам точки.
Re: подсчёт ссылок
Перевожу Heaps. Тут содержатся сведения о структуре данных, выделенных на куче.
https://tvoygit.ru/budden/ja-o-s/src/br ... -памяти.md
В частности, выясняется, что запись, выделенная на куче - это последовательно лежащие RecordBlockDesc, DataBlockDesc и собственно данные записи. Массив на куче - это ArrayBlockDesc, затем ArrayDataBlockDesc, за ним - данные.
Загадочно поле heapBlock в RecordBlockDesc/ArrayBlockDesc. Надо выяснить, что там находится, и тогда уже можно будет перевести все эти сущности.
Заполняется в NewRec->NewBlock->GetFreeBlock->LazySweep->InitFreeBlock
и заполняются они нулём. Спрашивается: а зачем тогда это поле вообще нужно?
https://tvoygit.ru/budden/ja-o-s/src/br ... -памяти.md
В частности, выясняется, что запись, выделенная на куче - это последовательно лежащие RecordBlockDesc, DataBlockDesc и собственно данные записи. Массив на куче - это ArrayBlockDesc, затем ArrayDataBlockDesc, за ним - данные.
Загадочно поле heapBlock в RecordBlockDesc/ArrayBlockDesc. Надо выяснить, что там находится, и тогда уже можно будет перевести все эти сущности.
Заполняется в NewRec->NewBlock->GetFreeBlock->LazySweep->InitFreeBlock
и заполняются они нулём. Спрашивается: а зачем тогда это поле вообще нужно?
Re: подсчёт ссылок
пытался искать, где же заполняется этот heapBlock, и попалось в модуле Reflection:
Код: Выделить всё
УкльНаЗаголовокБлокаПамяти* = укль {опасныйДоступКПамяти, неОтслСборщиком} на ЗаголовокБлокаПамяти;
ЗаголовокБлокаПамяти* = запись
следщ- : УкльНаЗаголовокБлокаПамяти;
адресЭтогоБлока-: адресВПамяти; (* sort key in linked list of memory blocks *)
разм-: размерМЗ;
адресНачалаДанных-, адресЗаКонцомДанных-: адресВПамяти
кон;