Add some more debug:
It appears that some timer events are not being picked up, I can see in the log that something which should have been signalled is not being run.
Enabling the log appears to make the situation worse.
This is a hang-over from the old polling scheduler. I've modified it to use relative times and pass the callback along with the TimeRequest so events get executed in the order they arrive.
The list of events is still in a heap sorted by expected execution time, but this may need to change to something more efficient for random lookups.
TimerRequests are removed from the message queue by WaitIO() which is ultimately called when the event is taken off the heap.
The event on the top of the heap is _not necessarily_ the one which signalled us, though, and we should probably be handling this better.