Now that we have our script profiler up and running, we instrument our script a little to mark regions we are concerned about. You can download that starting script here: [burn-console-1.profiler.msh] After running the script profiler, we get the performance breakdown:
Breakdown by line:
----------------------------
15%: Line 123 - if($colour -lt 20) { $colour -= 1 }
14%: Line 122 - if($colour -le 70) { $colour -= 3 }
11%: Line 124 - if($colour -lt 0) { $colour = 0 }
10%: Line 128 - $tempWorkingBuffer[$baseOffset -
8%: Line 117 - $colour /= 4.0
7%: Line 121 - if($colour -gt 70) { $colour -= 1 }
6%: Line 154 - $nextScreen[$row, $column] = `
6%: Line 113 - $colour = $screenBuffer[$baseOffset]
6%: Line 115 - $colour += $screenBuffer[$baseOffset + 1]
6%: Line 116 - $colour += $screenBuffer[$baseOffset +
5%: Line 114 - $colour += $screenBuffer[$baseOffset - 1]
5%: Line 109 - $baseOffset = ($windowWidth * $row) +
0%: Line 90 - if($random.NextDouble() -ge 0.20)
0%: Line 152 - for($column = 0; $column -lt $windowWidth;
0%: Line 94 - $screenBuffer[($windowHeight - 2) *
Breakdown by marked regions:
----------------------------
6%: updateScreen
0%: startFireLastRow
93%: propigate
0%: Unmarked
0%: main
It looks like we’re spending 93% of our time propagating the fire. When we investigate how we’re spending the time, none of the hot spots are individually egregious. Since we’re in such a tight loop, we’re spending most of the time comparing colours. We can be a little smarter with our ‘if’ statements, attempting to minimize the number of comparisons and variable assignments. Before optimization, we have 4 checks per loop, and (a weighted average of) just over 1 assignment per loop. If we write it as below, we reduce that to (a weighted average of) 1 check per loop, and (a weighted average even closer to) 1 assignment per loop.
if($colour -gt 70)
{
$colour -= 1
}
else
{
$colour -= 3
if($colour -lt 1)
{
$colour = 0
}
elseif($colour -lt 20)
{
$colour -= 1
}
}
This brings us up to 0.57 frames per second. A great improvement, but we’re obviously not done yet. We run the profiler again, and see that the hotspots have moved:
Breakdown by line:
----------------------------
13%: Line 141 - $tempWorkingBuffer[$baseOffset -
9%: Line 113 - $colour = $screenBuffer[$baseOffset]
9%: Line 117 - $colour /= 4.0
9%: Line 115 - $colour += $screenBuffer[$baseOffset + 1]
9%: Line 131 - $colour = 0
8%: Line 129 - if($colour -lt 1)
8%: Line 127 - $colour -= 3
7%: Line 121 - if($colour -gt 70)
7%: Line 116 - $colour += $screenBuffer[$baseOffset +
7%: Line 114 - $colour += $screenBuffer[$baseOffset - 1]
5%: Line 109 - $baseOffset = ($windowWidth * $row) +
5%: Line 167 - $nextScreen[$row, $column] = `
3%: Line 244 - $bufferCell = `
1%: Line 240 - $character =
0%: Line 252 - $paletteIndex++
0%: Line 241 - $fgColour =
0%: Line 242 - $bgColour =
0%: Line 165 - for($column = 0; $column -lt $windowWidth;
Breakdown by marked region:
----------------------------
5%: updateScreen
0%: startFireLastRow
90%: propigate
0%: Unmarked
5%: main
There’s not too much we can do, but there are a few lines representing access and manipulation of the $colour variable as we compute the average. So we’ll put those into one line:
$colour = ($screenBuffer[$baseOffset] +
$screenBuffer[$baseOffset - 1] +
$screenBuffer[$baseOffset + 1] +
$screenBuffer[$baseOffset + $windowWidth]) / 4.0
The frame rate barely changes, so let’s see what the new hot spots are:
Breakdown by line:
----------------------------
19%: Line 140 - $tempWorkingBuffer[$baseOffset -
13%: Line 113 - $colour = ($screenBuffer[$baseOffset] +
12%: Line 109 - $baseOffset = ($windowWidth * $row) +
11%: Line 126 - $colour -= 3
11%: Line 128 - if($colour -lt 1)
11%: Line 120 - if($colour -gt 70)
10%: Line 130 - $colour = 0
9%: Line 166 - $nextScreen[$row, $column] = `
1%: Line 240 - $fgColour =
1%: Line 243 - $bufferCell = `
0%: Line 239 - $character =
0%: Line 122 - $colour -= 1
0%: Line 251 -