Showing posts with label GC. Show all posts
Showing posts with label GC. Show all posts

Friday, May 15, 2009

Я тебя породил, я тебя и убью!

Я тебя породил, я тебя и убью!
Н. Гоголь "Тарас Бульба".
Старые ошибки или почему иногда, большое удобство плохо.

Если человеку дают очень удобное и красивое средство он теряет нюх и начинает ошибаться, конечно, потом он находит свои ошибки, и не считает, что все что блестит золото , но все таки. Как пример можно привести мелкие ошибки в решении которых я когдато участвовал (примеры относяться к .Net).

Как известно эта платформа обладает очень хорошим свойством как сборщик мусора, вот понимание его работы и вызвало ошибку: когда теряется ссылка на объект через некоторое время этот объект будет удален, но бывают некоторые особенности. Иногда остаются скрытые ссылки на этот объект, и как следствие он остается на вечно и скрытно жрет ресурсы: например окошко с созданным в нем таймером по которому в этот окошке , что то изменяется, вызывает такую особенность: система обрабатывает это окошко по особенному. В системе есть команда: 'выполнять по таймеру событие' и вся эта система, когда вы думаете уже мертва, начинает жить по собственным правилам, и не давать сборщику мусора удалить себя, так как есть круговая зависимость окошко->таймер->система и через некоторое время все ресурсы съедены и система уже не может создавать новые компоненты. Но и умереть она не может, так как не понятно, что происходит и нужно сообщить разработчикам или умереть, одно выполнить не можем, а другое не красиво, а решение простое: когда вам что то уже не нужно разрывайте и останавливаете связи сами, а не ждите, пока это сделает система, так хоть немного дольше проживете(в смысле программы).

Я тебя породил я тебя и убью... всегда сохраняйте взаимосвязь внутри приложения родитель -> потомок. Так как поток созданный в программе обладающей выше указанным багом некогда не умрет при исключении в основном потоке и программа постепенно 'захватит мир или моск'. В данном случае поток выполняющийся в программе был создан, как отдельный процесс не связанный с основным, в деструкторе основного потока он не уничтожался и потихоньку держал ресурсы всей программы. Решение было простое создавать не новый поток, а вызывать асинхронно делегат, который заменил этот поток.

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

Monday, December 22, 2008

Сборка мусора

Или GC(Garbage Collection) применимо к glib.

В glib относительно памяти есть договоренность, что если возвращается константный указатель. то его освобождать не нужно, а в обратном случае нужно. Так же для gobject существуют функции g_object_ref () и g_object_unref (). Это решает проблему с слежением за выделением памяти, но требует от разработчика чтобы он следил за выделением памяти и при каждом копировании указатяля делал соответствующий вызов ref/unref. Что не совсем удобно... Система автоматической сборки мусора в C# или Java более удобна, но требует соответствующей поддержки от компилятора. Хотя эта проблема решена в Vala, так как он автоматически добавляет вызовы удаления памяти в чистом виде в glib его нет.

Моя идея - добавить систему(на начальном этапе только для отладки): при каждом выделении памяти запоминать, где она была выделена(строка , файл и можно еще идентификатор потока) и к какому объекту привязана(области памяти) - затем при удалении удалять эту привязку, чтобы при вызове удаление родительского объекта можно было посмотреть какие области памяти остались не освобожденными и где их выделяли. В общем случае получается структура в виде дерева, где к каждому узлу(области памяти) привязывается привязывается список областей памяти выделенных для подчиненных по отношении к нему ресурсов и где они выделялись.

Отличие он настоящей сборки мусора - автоматически память не освобождается, только добавляется код отладки освобождения чтобы можно было посмотреть где выделялось. Очищать память автоматически не удастся(нужно придумывать систему макросов), что в общем случае делать не хочется или изменять компилятор. Оптимизация размещения объектов в памяти для glibc несколько теряет смысл так как все изменения указателей отслуживать сложно и нужно изменять код чтобы с непосредственно с указателями никто не работал и как-то выделял все ссылки в объектах чтобы можно было менять их расположение - что скорее всего особого смысла не имеет.

И по моему реализации системы отслеживания как инструмента отладки более перспективна и удобна. В дальнейшем сюда можно добавить и код регистрации открытия - закрытия файловых потоков

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