
8.2. И снова анализ
и оптимизация программы
Проанализируем теперь программу studex35. Для нее диаграмма исключения операций имеет следующий вид (рис. 8.4).
Рис. 8.4. Диаграмма исключения операций studex35
Как мы видим, операции записи пикселов в растр DIB составляют уже небольшую часть общего цикла рисования. Также уменьшилась доля времени для записи всех пикселов (setPixMyz). Необходимо проанализировать другие операции.
Ранее, в ходе анализа программы studex34, мы отмечали, что нельзя временно исключать операцию MyPolygon, так как изменится логика заполнения
Z-буфера — кроме полигонов в нашей программе рисуется и шар. И все же давайте сделаем отдельный анализ для цикла вывода многогранников, исключив На весь период измерений функцию Sphere: : Draw. ПОНЯТНО, ЧТО без
шара процесс создания изображения будет проистекать по-другому. Однако мы вынуждены пойти на это— когда сложно анализировать весь процесс в целом, необходимо попробовать разделить его на более простые составляющие.
Снова воспользуемся методом временного исключения. Замеры времени отражены на следующей диаграмме исключения для многогранников (рис. 8.5).
Рис. 8.5. Операции вывода многогранников Определим общее время, затрачиваемое для работы функций:
Глядя на эти цифры, можно предположить, что необходимо оптимизировать функцию MyPoiygon, которая вносит наибольший вклад в общее время. Однако, для того чтобы выяснить, как именно ее оптимизировать, следует проанализировать структуру программы, а точнее— иерархию вложенных функций. Вложенной функцией мы будем для краткости называть функцию, которая вызывается в теле другой функции. Таким образом, общее время работы
некоторой функции складывается из вызовов вложенных функций (если они есть) плюс время работы операторов собственно этой функции
Для анализа каждой функции будем в первую очередь оценивать время собственной работы, а не время работы вложенных функций. Это время, очевидно, равно
На рис. 8.6 изображена иерархия вложенности функций studex35.
Рис. 8.6. Вложенность функций
Из этой схемы видно, что собственное время работы функции MyPolygon составляет разность между общим временем работы этой функции и временем работы функций Ref lectionColQE..H MyLineHor: ----
Для остальных функций собственное время составит
Обратим внимание на эти цифры. Подозрительно много времени занимают операции тела функции MyLineHor. Возможно, ее следует оптимизировать в первую очередь. Следующим в этом списке фигурирует тело функции setPixMyz— 15 сек. Собственное время работы операторов тела функции MyPolygon относительно невелико.
План оптимизации программы может быть таким:
1. Совершенствование функции MyLineHor.
2. Уменьшение количества уровней вложения функций— можно сэкономить время, которое расходуется на вызовы вложенных функций и пере-
дачу им значений аргументов. Для этого код функции setPixRastrMai расположим непосредственно в теле функции setPixMyz. Отдельная функ-? ция SetPixRastrMem нам уже не нужна.
Приведем текст третьего варианта программы (studex36) только для оптимизированных функций. Другие функции остались без изменений.
Часть файла studex36.cpp:
I
В результате второго шага оптимизации программа осуществляет полный цикл вывода многогранников за 49 секунд (вместо 73 для предыдущего варианта). Замена типов double на float дает немного — где-то одну-две секунды. Повышения скорости в основном достигнуто за счет усовершенствования
функции MyLineHor и включения кода записи пикселов DIB в тело функции setPixMyZ. Функция SetPixRastrMem ликвидирована (ее делать inline не имеет смысла).
Восстановим работу программы в полном объеме — разблокируем sphere:: Draw и сделаем измерения времени. Полный цикл рисования составляет 65 секунд (предыдущий вариант был 88 секунд).
Таким образом, мы прошли два шага от первого варианта (studex34) и уменьшили время графического вывода от 807 до 65 секунд — то есть более! чем в 12 раз. Оптимизировать можно бесконечно любую программу, в том числе и последний вариант. Например, использовать ассемблер для программирования некоторых критических функций. Однако это тема уже для другого разговора...
Главное, что здесь желательно увидеть, — мы находились в рамках только одной технологии создания графических программ (программирование на основе функций API Windows), хотя результаты программирования могут существенно отличаться.
Подобная методика анализа может использоваться не только для графических программ.