Теперь первое правило всегда «Не оптимизируйте преждевременно». Вы должны быть уверены, что вам нужна эта оптимизация по сравнению с более чистым кодом.
Теперь в Game of Life вы изначально смотрите на довольно пустой экран. Однако по мере продолжения игр будет заполняться все больше и больше ячеек, в конечном итоге вся доска. Теперь правила GOL предписывают, что большинство этих ячеек будут меняться от одного цикла к другому.
Вам также необходимо понять, что означает "аннулирование" региона. В Windows недействительные области «складываются», образуя «область обновления», так что сообщение WM_PAINT может сообщить программе, какие части экрана должны быть нарисованы. В обработчике событий Paint вы используете RectVisible
, чтобы определить, нужно ли обновлять ячейку.
Другими словами, «стоимость» выполнения метода 1 (при условии, что размер платы n):
(n x n) x (redraw cell + update cell on screen)
Обратите внимание, что я предполагаю, что вы не забываете делать четкий экран перед тем, как рисовать ячейки, в противном случае ячейки, которые были "живыми" в течение последнего цикла, останутся на экране. Таким образом, предполагается, что вы рисуете действующую или пустую ячейку по всему экрану.
«Стоимость» выполнения метода 2:
(v) x (redraw cell + update cell on screen) + (n x n) x (RectVisible call)
где v = количество ячеек, которые изменились (см. Примечание ниже).
Итак, метод 1 быстрее, чем метод 2, если:
(n x n) x redraw < v x redraw + (n x n) x RectVisible
n2 x (redraw - RectVisible) < v x redraw
v > ((redraw - RectVisible) / redraw) x n2
v > (1 - RectVisible/redraw) x n2
Другими словами, количество измененных ячеек должно быть больше единицы за вычетом отношения (стоимость RectVisible / стоимость перерисовки). Теперь RectVisible
обычно довольно быстрый по сравнению с отображением растрового изображения на экране, особенно если ваши ячейки имеют высокое разрешение. Следовательно, Rectvisible / redraw обычно очень мало, что делает метод 1 быстрее, чем метод 2, только когда, скажем,> 99% платы изменяется одновременно, что маловероятно.
Другими словами, вы обнаружите, что метод 2 обычно дает более высокую производительность, поскольку DrawImage
обычно пропускает всю операцию, если изображение должно быть нарисовано вне области отсечения (то есть не в области обновления).
ПРЕДУПРЕЖДАЙТЕ - ВАШ КОД, КАК ЭТО НЕ БУДЕТ
Однако ваш код в методе 2 не будет работать. Вы должны помнить, чтобы «убрать» «мертвые» клетки, которые имели «живые» клетки в течение последнего цикла. Другими словами, вы лишаете законной силы клетки, которые «изменились», а не только те, которые «живы». Клетки, которые «живы» в течение нескольких циклов, , а не должны быть признаны недействительными. Таким образом, логика в вашем методе MyInvalidate
имеет недостатки.