Previously we were able to reduce the work involved in the step-by-step redraw, this was achieved by only drawing the cells that had changed state in that step and was very effective at speeding the clock up. Unfortunately, as evidenced in the profile below, when the clock first loads the cells have no previous state and we must draw them all.

Our goal, by my logic, is still to reduce the number of calls to the fill
method. The next way we can attempt to do this is by calling it a limited number of times to produce a block of them and then copying that block across the entire canvas using the drawImage
method. We could pre-fill a single cell and copy that 1,109,556 but we're then left with an awful lot of copying operations. The optimal way is somewhere between these 2 extremes.

I've chosen an arbitrary block size of 100x100 to try this with, the rough code looks like this:
private fillWithDeadCells() {
var cells: number[][] = [],
x: number,
y: number,
block: HTMLCanvasElement,
ctx: CanvasRenderingContext2D,
resolution: ISize;
block = document.createElement('canvas');
block.width = 100;
block.height = 200;
ctx = block.getContext('2d');
resolution = this.getResolutionForCanvas(block);
for (y = 0; y < resolution.y; ++y) {
cells[y] = [];
cells[y].length = resolution.x;
}
this.render(null, cells, ctx, true);
for (x = 0; x < this.canvas.width + block.width; x += block.width) {
for (y = 0; y < this.canvas.height + block.height; y += block.height) {
this.ctx.drawImage(block, x, y);
}
}
}
After profiling this we can see an improvement on the time spent on the initial render:

Still to come
Whilst the performance is now acceptable for the resolution we were working at I want to take it further and up the resolution by a factor of 10 next time. I think we'll see a significant slow down and it will probably be relatively localised to the methods that calculate the next set of live cells. The current implementation of this is crude and so we'll take a look at what we can do to improve on it.
Monday to Friday, 9ish-5ish I'm sitting for most of the time. When I come home and work on other projects I'm still sat down. I'm bored of sitting. I can never find the right position, I lean towards the screen when I concentrate, my hand gets cold as my wrist rests on the desk, and I occasionally panic when I lean my chair too far back and forget that it's perfectly safe.
As I was closing down late last night I was standing up just finishing a few last bits and bobs and I realised that keyboards can be used without an accompanying chair. So today I vowed to try standing up to develop and have constructed a luxury environment in which to try this.

I knew keeping these boxes around would come in handy at some point. The Xbox box positions the keyboard at just the right height for my forearms to be horizontal and comfortable (so far). I had to raise my speakers up too else the sound was too distant - they're only cheap speakers.
What you can't see under the shoebox that the monitor stands on, is a half full crate of Desperados beer. This is my least favourite part so far as the beer is now inaccessible, but removing them reduces the structural integrity of the crate too much for my comfort. The whiskey under the speaker is still accessible so life goes on.
I'm going to try using my computer like this for a while and see how I get on.
I have two things: the need for an event hub in my Typescript application, and a mild case of NIH syndrome.
I say mild because from brief searching around I can't find any existing library that suits my needs so I can either shoehorn the design for my application to fit something else or invest the same time and effort into creating one that fits like a glass slipper.
My Requirements
I want to be able to register for events like this:
register('AssetUpload::Queued', asset => this.addToUi(asset))
register('AssetUpload:42:UploadComplete', asset => this.handleUploadComplete(asset))
register('AssetUpload:42:*', (asset, event) => this.handleAllEventsForAsset(event))
register('*', (data, event) => console.log({event: event, data: data}))
This segmented event name structure may not turn out to be the best but it's what I've come up with so far in order to allow arbitrary specificity when subscribing to events. Events should always be triggered as specifically as possible and allow the hub to filter the recipients.
An asterisk should match one or more segments, and an empty segment should match exactly one segment. So:
AssetUpload:42:Queued
would trigger both AssetUpload:*:Queued
and AssetUpload::Queued
,
Asset:42:Upload:Queued
would only trigger Asset:*:Queued
but not Asset::Queued
.
Implementation
I'm implementing this naively for the time being as my project is still in its infancy and performance/robustness will be addressed once some core functionality is in place.
When registering for an event, the event name will be turned into a regular expression and pushed into an array. When an event is triggered the loop is iterated, and if the regular expression for a registered event matches, the associated handler function is called.
There are two replacements that need to be made on the event name to turn it into the correct regular expression. An asterisk must be turned into the greedy .*
operator, and an empty segment must have [^:]*
inserted into it to allow matching of a single segment.
Feeding the above into the keyboard results in the below snippet.
module mc {
export class EventHub {
private handlers: Array<EventHandler>;
constructor() {
this.handlers = [];
}
public register(event: string, handler: (data: any) => void ): void {
this.handlers.push(new EventHandler(event, handler));
}
public trigger(event: string, data?: any): void {
for (var i = 0; i < this.handlers.length; ++i) {
if (this.handlers[i].regex.test(event)) {
this.handlers[i].handler(data, event);
}
}
}
}
class EventHandler {
public handler: (data: any, event: string) => void;
public event: string;
public regex: RegExp;
constructor(event: string, handler: (data: any, event: string) => void ) {
this.handler = handler;
this.event = event;
this.regex = new RegExp(event.replace('*', '.*').replace('::', ':[^:]*:'));
}
}
}
Shortcomings
This is far from a complete implementation, there is no way to unregister from an event and it's probably not the most performant, but it fits my needs for the time being. I shall revisit this when it becomes a problem.
I've been doing a lot of optimisation work recently and so I decided to take a quick look at the performance of the Game of Life Clock. It was written quickly with little thought to anything beyond getting a result on the screen so there should be plenty of room for improvements. With a small 500 x 200 canvas there won't be any noticeable improvements so a 5,000 x 2,000 canvas should make things a bit more interesting as that results in 1666 x 666 cells.
Firstly, a quick overview of the process:
- Create a 2-dimensional array to represent all of the cells,
- Print a set of characters into the array,
- Draw each cell into the canvas,
- Calculate next step,
- Draw each cell into the canvas, back to 4, and repeat.
With that in mind there are a few places that have the potential to be bottleneck:
- Printing the characters into the array of cells. There are 35 cells per character to set, which isn't too many, but we're currently only printing 5 characters at a time.
- Drawing the cells into the canvas. In a 1666 x 666 grid that makes 1,109,556 cells which could be slow depending on the canvas implementation.
- Calculating the next step. This iterates over all of the cells and then reads the 8 surrounding cells, so accessing roughly 8,876,448 array indexes.
Profiling
Running the Chrome profiler for a few moments yields the following:

We can clearly see that the majority of time is spent in the fill
method of the canvas context, so our first goal will be to reduce the number of calls to this method. Without calculating any statistics, observations of the visualisation indicate that relatively few cells actually change state in each step. With this in mind the code can be changed to not redraw every cell, but only those that need redrawing.
Our render method goes from:
// clear canvas
for (y = 0; y < nextCells.length; ++y) {
for (x = 0; x < nextCells[y].length; ++x) {
// fill cell
}
}
To
for (y = 0; y < nextCells.length; ++y) {
for (x = 0; x < nextCells[y].length; ++x) {
if (oldCells && oldCells[y][x] === nextCells[y][x]) {
continue;
}
// clear cell
// fill cell
}
}
A follow up profile shows a vast improvement in the step-by-step rendering:

Still to come
This optimisation was very simple but also effective. What this doesn't address, however, is the first render to a blank canvas, it's still filling 1,109,556 cells. I'm confident we can reduce the step-by-step rendering time even more, but next up we'll take a look at reducing that initial render time.
It’s been a bit of a slow Sunday, usually I’m ok with that, but when I realised I’d chosen housework over working on my pet projects I decided to start a new one. So I set up this website to make myself start writing about things. For my first post I decided to create a clone of something I saw in my feed earlier on.
The article was about a Game of Life Clock that somebody has built. The idea is simple, the clock is constructed from an LED array and the time is refreshed each minute. For each second between the minutes, however, the display follows the rules of Conway’s Game of Life, gradually changing until the next minute is displayed. The whole thing looks much more impressive in the hardware version, you should check it out.
You can view the source over on github if you’re interested. http://github.com/mattsgitcode/gameoflifeclock
I based the font on a freely available dot matric font from http://www.fontspace.com/jecko-development/jd-lcd-rounded. I’ll fill in the remainder of the font characters shortly and see what interesting patterns different phrases produce