Казалось бы ничего особо сложного, но в процессе работы вылезла принеприятная проблема : начались кошмарные утечки памяти. НА каждые 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 изумительно работает с малыми объёмами данных и короткоживущими переменными. С долгоживущими, да ещё и толстыми - это просто мрак кромешный. Избегайте их. И следите за памятью в Профайлере.