🎨 Графическое программирование на C#

← Вернуться к модулю 3

Урок 3.4: Практика: Оптимизация приложения

Модуль 3 ⏱️ ~2 часа

📌 Ключевые моменты этого урока:

  • Профилирование показывает где именно теряется производительность
  • Caching объектов (Pen, Brush) экономит память и время на переиспользование
  • FPS счётчик помогает оценить результаты оптимизации (цель: 60+ FPS)
  • Комбинация всех техник: DoubleBuffered + partial Invalidate + LockBits для максимума
  • Оптимизация - это измерение, поиск узких мест, применение техник, повторное измерение

Анализ узких мест

Перед оптимизацией необходимо найти узкие места в коде:

  • Используйте профилировщик Visual Studio (Debug → Performance Profiler)
  • Измеряйте время выполнения критических участков Stopwatch
  • Ищите частые вызовы Invalidate (выводятся в Debug)
  • Проверяйте создание объектов в циклах (ГЛАВНЫЙ враг производительности!)

Применение техник оптимизации

1. Включите двойную буферизацию

this.DoubleBuffered = true;

2. Используйте частичную перерисовку

this.Invalidate(updateRegion);

3. Кэшируйте объекты (КЛЮЧЕВОЙ СОВЕТ!)

// Плохо: создание в цикле
for (int i = 0; i < 1000; i++)
{
    Pen pen = new Pen(Color.Black);
    g.DrawLine(pen, ...);
}

// Хорошо: переиспользование
Pen pen = new Pen(Color.Black);
for (int i = 0; i < 1000; i++)
{
    g.DrawLine(pen, ...);
}

Измерение FPS (правильный способ с Stopwatch)

// В конструкторе формы
private System.Diagnostics.Stopwatch fpsStopwatch = new System.Diagnostics.Stopwatch();
private int frameCount = 0;
private double currentFps = 0;

// Инициализация
public Form1()
{
    InitializeComponent();
    fpsStopwatch.Start();
}

// В Paint событии (вызывается для каждого кадра)
private void Form1_Paint(object sender, PaintEventArgs e)
{
    // Ваш код рисования здесь
    e.Graphics.DrawString($"FPS: {currentFps:F1}", Font, Brushes.Black, 10, 10);
    
    // Счёт кадров
    frameCount++;
    
    // Каждую секунду обновляем FPS
    if (fpsStopwatch.ElapsedMilliseconds >= 1000)
    {
        currentFps = frameCount * 1000.0 / fpsStopwatch.ElapsedMilliseconds;
        frameCount = 0;
        fpsStopwatch.Restart();
    }
}

// Более простой способ с Timer:
private System.Windows.Forms.Timer gameTimer = new System.Windows.Forms.Timer();
private int frameCount = 0;
private DateTime lastSecond = DateTime.Now;

// В конструкторе
gameTimer.Interval = 16; // ~60 FPS (1000ms / 60 ≈ 16ms)
gameTimer.Tick += (s, e) => 
{
    frameCount++;
    if ((DateTime.Now - lastSecond).TotalSeconds >= 1)
    {
        this.Text = $"FPS: {frameCount}";
        frameCount = 0;
        lastSecond = DateTime.Now;
    }
    this.Invalidate();
};
gameTimer.Start();

Таблица сравнения техник оптимизации

Техники оптимизации производительности

Сравнение эффективности техник оптимизации

Сравнение до и после оптимизации

Создайте версию приложения без оптимизаций и с оптимизациями. Сравните:

  • FPS (кадров в секунду)
  • Использование CPU
  • Плавность анимации
  • Отсутствие мерцания

Практическое задание

Задание: Оптимизация приложения

  1. Создайте приложение с множеством объектов (100+)
  2. Примените все изученные техники оптимизации
  3. Добавьте измерение FPS
  4. Достигните стабильных 60 FPS

Проверка знаний

Ответьте на вопросы, чтобы проверить, насколько хорошо вы усвоили материал:

1. Усвоили ли вы основные концепции урока?
  • Да, материал понятен
  • Частично понятен
  • Нужно повторить
  • Не понял
2. Готовы ли вы применить изученное на практике?
  • Нет, нужно еще изучить
  • Да, готов попробовать
  • Возможно
  • Не уверен
3. Что такое FPS?
  • Количество кадров в секунду
  • Скорость процессора
  • Размер файла
  • Количество пикселей