4. Начинаем собирать мусор
• Поколение 0 заполнено
• Вызван метод GC.Collect
• Свободной памяти осталось мало
• Выгрузка домена приложения
• Завершение работы CLR
7. Поколения
• Чем младше объект, тем короче его время
жизни
• Чем старше объект, тем длиннее его время
жизни
• Убрать часть кучи быстрее, чем всю кучу
• Тяжело перемещать что-то большое
9. Куча больших объектов (LOH)
• Объекты размером от 85000 байт
• Объекты не перемещаются
• Хорошая практика: пулинг больших объектов
No more memory fragmentation in .NET 4.5.1:
GCSettings.LargeObjectHeapCompactionMode =
GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect(); // This will cause the LOH to be compacted (once).
12. Паттерн Disposable
// Design pattern for a base class.
public class Disposable : IDisposable
{
private bool disposed = false;
//Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
// Set large fields to null.
disposed = true;
}
}
// Use C# destructor syntax for finalization code.
~Disposable()
{
Dispose(false); // Simply call Dispose(false).
}
}
13. Типичная ошибка
public static class Global
{
public static event EventHandler Update;
}
public class Foo
{
public Foo()
{
Global.Update += OnUpdate;
}
~Foo()
{
Global.Update -= OnUpdate;
}
private void OnUpdate(object sender, EventArgs e)
{
// Some logic
}
}
16. Режимы работы GC
• Рабочая станция / сервер
• Однопоточный / фоновый (конкурентный)
17. GCLatencyMode
• Batch — Отключает фоновую сборку
• Interactive — Включает фоновую сборку
• LowLatency — Сборка поколения 2
выполняется только при GC.Collect() или
малом количестве свободной памяти
• SustainedLowLatency — Продолжительные
периоды нежелательной сборки мусора
18. Ручное управление
• Ручной вызов сборки мусора GC.Collect()
GCCollectionMode ∈ { Default, Forced,
Optimized}
• AddMemoryPressure() и
RemoveMemoryPressure()
• class MemoryFallPoint
19. Время вызова сборщика мусора
using System;
using System.Threading;
public static class Program {
public static void Main() {
var t = new Timer(TimerCallback, null, 0, 2000);
Console.ReadLine();
}
private static void TimerCallback(Object o) {
Console.WriteLine("In TimerCallback: " + DateTime.Now);
GC.Collect();
}
}
20. Время вызова сборщика мусора
public class ImageWithCircle
{
private const int Size = 10000;
private readonly IplImage image;
public ImageWithCircle()
{
image = Cv.CreateImage(new CvSize(Size, Size), BitDepth.U8, 3);
DrawCircle();
}
~ImageWithCircle()
{
Cv.ReleaseImage(image);
}
public void Save()
{
image.SaveImage("image.tif");
}
public void DrawCircle()
{
image.FloodFill(new CvPoint(Size / 2, Size / 2), CvColor.White);
image.Circle(new CvPoint(Size / 2, Size / 2), Size / 4,
CvColor.Random(), 10);
}
}
21. Время вызова сборщика мусора
public class ImageWithCircle
{
private const int Size = 10000;
private readonly IplImage image;
public ImageWithCircle()
{
image = Cv.CreateImage(new CvSize(Size, Size), BitDepth.U8, 3);
DrawCircle();
}
~ImageWithCircle()
{
Cv.ReleaseImage(image);
}
public void Save()
{
image.SaveImage("image.tif");
GC.KeepAlive(this);
}
public void DrawCircle()
{
image.FloodFill(new CvPoint(Size / 2, Size / 2), CvColor.White);
image.Circle(new CvPoint(Size / 2, Size / 2), Size / 4,
CvColor.Random(), 10);
}
}
23. Диагностика
• MEMORY LEAKS: THE EASY WAY
Not in this talk. Shell out $500 for a decent
memory profiler.
(c) Sasha Goldshtein
24. Диагностика
• MEMORY LEAKS: THE EASY WAY
Not in this talk. Shell out $500 for a decent
memory profiler.
(c) Sasha Goldshtein
• sos.dll
• sosex.dll
• Dumps
• ...