We left off last time with a naive working implementation of the Game of Life using XAML under Metro. When Abrash did his first profiling, it turned out the bulk of time was spent determining a cell’s next state and so he explored that path. Our situation is different.

And digging a bit deeper into DrawCell, we see why:

Apparently we have two problems:

  1. Although we have an indexer to Canvas.Children, it seems unlikely that there is a direct index backing the collection. If there was, that line should take an inconsequential amount of time
  2. Setting the fill to a new brush each time is very expensive.

Neither of these seem to difficult to deal with, so let’s make the required changes.

We can keep our own index to each Rectangle via a dictionary when we originally create the cells.

private readonly Dictionary<int, Rectangle> cellIndexDisplayMap;

// near the start of the constructor
cellIndexDisplayMap = new Dictionary<int, Rectangle>();

// right after canvas.Children.Add(cell)
cellIndexDisplayMap[y * numberCellsAcross + x] = cell;

And we may as well just have one brush for each color that all the cells can share.

private readonly SolidColorBrush blackBrush;
private readonly SolidColorBrush whiteBrush;

// near the start of the constructor
blackBrush = new SolidColorBrush(Colors.Black);
whiteBrush = new SolidColorBrush(Colors.White);

Which gives us a new DrawCell implementation.

public void DrawCell(int x, int y, bool on)
  var cellRectangle = cellIndexDisplayMap[y * numberCellsAcross + x];
  cellRectangle.Fill = on ? whiteBrush : blackBrush;

Things are slightly better now

and it looks like we are at the end of where we can optimize in DrawCell

There is one other place left to tackle: GetCellState, which is still using about 10% of the time. This is where we skip ahead to the neat solution at the end of Chapter 17 :)

(The code so far)