Страница 1 из 1

Garbage Collector и большие объёмы данных.

СообщениеДобавлено: 24 дек 2009, 09:41
Neodrop
Столкнулся с задачей написать сохранение позиции и вращения 5000 объектов в каждом кадре.
Казалось бы ничего особо сложного, но в процессе работы вылезла принеприятная проблема : начались кошмарные утечки памяти. НА каждые 75 000 записей, я получал объём используемой памяти, приблизительно 3-4 метра.
Писал сперва в List<>. После сохраненения данных на диск, вызывал ему .Clear()
И вот так новость - память не освобождалась и после 10 - 15 циклов я получал переполнение Memory Hip и вылет из приложения.

После штудирования информации о GC, выяснилось, что переменные, к которым система обратилась более одного раза, автоматически маркируются как "долгоживущие" и коллектор перестаёт обращать на них внимание. Всё бы ничего и, может быть, если бы данные были обычными, то не было бы и проблем, но в моём случае, я хранил не Vector3, а собственный класс, ещё и упакованный в dll (не буду объяснять, почему, но иначе невозможно было) и, коллектор оценил их как неуправляемые и начихал на них.
Что я только не перепробовал. Помогло следующее:

Все массивы программы переписал на фиксированные (фтопку generics).
Класс сохраняемых данных унаследовал от IDisposable и переопределил диструктор Disposable()
При удалении экземпляра, обязательный вызов Disposable()
В потоке, пишущем данные на диск, прописал процедуру очищения массива данных (null не очищает) и принудительно вызвал коллектор после каждого очищения.
Код: Выделить всё
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();


По завершении всех этих действия, я смог писать 142 цикла (75000 записей в каждом) не теряя ни метра памяти.

Вывод : GC изумительно работает с малыми объёмами данных и короткоживущими переменными. С долгоживущими, да ещё и толстыми - это просто мрак кромешный. Избегайте их. И следите за памятью в Профайлере. :-B

Re: Garbage Collector и большие объёмы данных.

СообщениеДобавлено: 24 дек 2009, 10:07
Tolking
Ага... Тоже GC напрягает работает там как-то без моего контроля :). Когда начинал, то даже бесило, что ненужно напрямую дистроить объекты. Но пока не сталкивался с траблами.

В твоем случае засада именно с неуправляемыми данными... Если бы они были .нет то проблемы бы невозникло, GC снес бы все объекты на которые нет ссылок (которые не "сохранены" в переменных или в других объектах) т.е. к которым ты ну никак уже несможешь обратиться из кода по технологии .нет. (он и так сносил твою обертку над данными, но данные он сносить немог, ибо фиг его знает, что ты с ними в ДЛЛ можешь делать? Может там свой GC и если он убьет данные програма крашнится?

Re: Garbage Collector и большие объёмы данных.

СообщениеДобавлено: 24 дек 2009, 11:04
Neodrop
Они .NET
Dll с классом сохраняемых данных написана на C#

Вот класс сохраняемых данных (без функций копирую). Мне не кажется, что он очень сложен :

Код: Выделить всё
[System.Serializable]
    public class Data
    {
        private float vx, vy, vz, qx, qy, qz, qw;
    }


Семь обыденных float чисел.

Re: Garbage Collector и большие объёмы данных.

СообщениеДобавлено: 24 дек 2009, 11:10
Neodrop
А вот, как он выглядит в работающем варианте. Данные удаляются качественно, если руками вызвать Dispose()

Код: Выделить всё
[System.Serializable]
    public class Data : IDisposable
    {
        private float vx, vy, vz, qx, qy, qz, qw;

        public Data(Vector3 pos, Quaternion rot)
        {
            vx = pos.x;
            vy = pos.y;
            vz = pos.z;

            qx = rot.x;
            qy = rot.y;
            qz = rot.z;
            qw = rot.w;
        }

        public Data(Transform tr)
        {
            ResetData(tr);
        }

        public void Dispose()
        {
        }

        public void ResetData(Transform tr)
        {
            vx = tr.position.x;
            vy = tr.position.y;
            vz = tr.position.z;

            qx = tr.rotation.x;
            qy = tr.rotation.y;
            qz = tr.rotation.z;
            qw = tr.rotation.w;
        }

        protected Vector3 GetPosition()
        {
            return new Vector3(vx, vy, vz);
        }

        protected Quaternion GetRotation()
        {
            return new Quaternion(qx, qy, qz, qw);
        }

        public void SetPosition(Transform tr)
        {
            tr.position = GetPosition();
            tr.rotation = GetRotation();
        }
    }
}

Re: Garbage Collector и большие объёмы данных.

СообщениеДобавлено: 24 дек 2009, 11:13
Tolking
Нифига себе! А с чего, тогда, ты взял что GC посчитал данные неуправляемыми?

Интиресно, Юнититим GC непереопределяли?

Re: Garbage Collector и большие объёмы данных.

СообщениеДобавлено: 24 дек 2009, 11:15
Neodrop
А вот чёрт его знает. Вряд ли. Почти уверен, что нет.
Для своих классов, может что-то своё добавили, но в целом - на 100% используется Mono GC
Заметьте, что Dispose пустой и всё работает чики-чики. Но, только если вызвать его руками.

Re: Garbage Collector и большие объёмы данных.

СообщениеДобавлено: 24 дек 2009, 11:24
Tolking
А Data - то не в моно наверное? Может из-за этого? ИХМО надо забагрепортить эту штуку.

Re: Garbage Collector и большие объёмы данных.

СообщениеДобавлено: 24 дек 2009, 11:26
Neodrop
Чего не в MONO ? Data это просто название класса. В виду того, что он живёт в моём namespace, я могу задавать ему любое имя, не боясь перехлёстов.
Имя тут точно ни при чём.
А репортить.. Это надо демку писать, а мне недосуг.

Re: Garbage Collector и большие объёмы данных.

СообщениеДобавлено: 27 сен 2010, 13:52
Fox Rex
Хотя тема старая. Все таки вставлю свои 3 копейки. GC начинает работать только при переполнении кучи, что значит он может начинать свою работу в самые неудобные моменты, что может плохо сказаться на производительности. Поэтому в самые удобные моменты необходимо вызывать принудительную сборку мусора. Если это делать при удалении ссылки на объект, то лучше это делать в аналоге деструктора, в .NET если мне не изменяет память он называется финализатором. В нем так же удобно освобождать другие занятые ресурсы.

Re: Garbage Collector и большие объёмы данных.

СообщениеДобавлено: 27 сен 2010, 15:04
Neodrop
Это настоятельно нерекомендовано UT. Тем более, что объекты [unity 3D] Unity удаляются собственным сборщиком.

Re: Garbage Collector и большие объёмы данных.

СообщениеДобавлено: 27 сен 2010, 16:53
Fox Rex
Вот и хорошо, одной заботой меньше.