.NET Framework - Возможные классы, не требующие памяти?
На днях я исследовал утечку памяти, которая запускала приложение с ~ 50 МБ до ~ 130 МБ в течение двух минут. Оказывается, проблема была в классе ConcurrentQueue. Внутри класса хранится связанный список массивов. Когда элемент выгружается из ConcurrentQueue, индекс в массиве сталкивается, но элемент остается в массиве (т.е. Он не установлен в null). Весь массив node отбрасывается после достаточного количества очередей /dequeues, поэтому это не технически является утечкой, но если положить большие объекты в ConcurrentQueue, это может быстро выйти из-под контроля. В документации не упоминается об этой опасности.
Мне было интересно, какие другие потенциальные ловушки памяти находятся в библиотеке базового класса? Я знаю о Подстроке один (то есть, если вы вызываете подстроку и просто держитесь за результат, вся строка будет по-прежнему в памяти). Любые другие, с которыми вы столкнулись?
Ответы
Ответ 1
Вы правы. Ошибка находится в методе System.Collections.Concurrent.ConcurrentQueue<T>+Segment.TryRemove(out T, ref ConcurrentQueue<T>.Segment)
.
Если вы посмотрите на этот метод в Reflector, вы увидите следующую строку:
result = this.m_array[low];
После него должна быть следующая строка:
this.m_array[low] = default(T);
Для справки вы можете увидеть, как это правильно реализовано в методе System.Collections.Generic.Queue<T>.Dequeue()
.
Ответ 2
Хотя это не прямая утечка памяти или специфическая для .net/BCL, существует конкатенация строк (с использованием проблемы + =). Это довольно интенсивный процессор в циклах из-за большого сбора мусора.
Ответ 3
В ConcurrentQueue будет сохранено максимум 31 объект, выделенный из очереди. Это не должно представлять огромную проблему, если вы не имеете дело с действительно большими объектными графами.
В любом случае, это не имеет смысла, используя ConcurrentQueue, если у вас недостаточно места для размещения 32 объектов...