Master of time, or about benefits of server updates

As pointed out in some previous post, there are some disadvantages to calculating newarena state on server only when some client sends update. There is also a disadvantage to sending server updates on every client action – this puts a lot of stress on server (10 players, sending 10 updates a second, would mean server has to send 10×10=100 updates to server per second; 10 updates from client a second is really low number).

First I thought that I will address this simply by having arena raise event every time it thinks update is needed (so 30-60 times per second). After solving initial problem with events in SignalR hubs, it got to me – since there is no hub, there can be a time (and that will often be the case) when there is no one to handle event. Well, that’s easy – I will create my own hub. Well, not so fast – you can’t just do that. Hubs need to be created by hub pipeline, and it is not something I want to mess with. Well, that’s a pity. What should I do?

Thankfully SignalR creators thought about such use case and came up with possible solution. What is required is to create class that will take over some of the hub possibilites, like communicating with clients, make it singleton (well, not necessarily, but it works for me at this point), and subscribe to timer events in this class. This class will always be in memory (at least when I want it to handle my timer request), it will do what it needs and then send updates to clients like normal hub. From client point of view nothing really changes – they will all get normal updates in javascript like before.

Show me the code you say:

public class ArenaTicker
{
    private readonly static ArenaTicker _instance = new ArenaTicker(GlobalHost.ConnectionManager.GetHubContext<RaimHub>().Clients);
    private const int _updateInterval = 1000 / 60;

    private readonly IHubConnectionContext<dynamic> _clients;
    private readonly Timer _timer;

    public static ArenaTicker Instance {  get { return _instance; } }

    private ArenaTicker(IHubConnectionContext<dynamic> clients)
    {
        _clients = clients;
        _timer = new Timer(UpdateArena, null, _updateInterval, _updateInterval);
    }

    private void UpdateArena(object state)
    {
        var go = RaimHub.arena.UpdatePositions(DateTime.Now);
        _clients.All.PlayerMoved(go);
    }
}

What is going on is – there is private constructor so there will be guaranteed only one instance of this class. In it, it takes hub context. As you can see when creating this instance I’m hooking up to GlobalHost.ConnectionManager to get the context. It is slow operation so it should be done rarely, possibly just once per application runtime (or maybe one for each arena I need to update maybe?). This context will get updated with every client that connects, disconnects etc., just like in normal hub. Then there is a timer, that ticks 60 times per second (but easly adjustable to any other frame rate). It will call update on arena and then notify all clients on new arena state.
Please forgive the little ugliness of the code around getting arena – there is a static instance of this class in hub, I did not move it anywhere else since for a moment it does its job.

One more thing – notice that the code that returns objects to client changed a little bit. Before it looked like this;

_clients.All.PlayerMoved(RaimHub.arena.GameObjects);

This however resulted in issues with collection being changed when iterated over. That’s not good, I can’t have server crushing every time new player registers or some player shoots. This is now changed to return set of objects that were returned from update method. And it takes care of returning immutable collection when inside lock (to avoid changing collections when doing update to arena state).

public IEnumerable<IGameObject> UpdatePositions(DateTime? updateTimestamp)
{
    ...
    lock (_lock)
    {
        ...
        return GameObjects.ToArray();
    }
}

And now server is running 60 “frames” every second, always having pretty actual state, limitting number of updates to clients and improving on collision detection.

jQuery promises: done vs then

Imagine that, while working in jQuery and javascript, you want to trigger one task and once it is finished you want to trigger another one. You might come up with something like this:

var d1 = $.Deferred();
var d2 = $.Deferred();

d2.done(function() { console.log("d2 done")});

d1.done(function() { console.log("d1 done")})
.done(function () {
      setTimeout(function () {
        d2.resolve();
      }, 1000);
      return d2;
  })
  .done(function () {console.log("both done")});

console.log("start");
d1.resolve();

jsfiddle.net/bLh9eo2f/

Timeout in d2 resolving is just to simulate time taking task. And expected output would be like:

start
d1 done
d2 done
both done

However if you run it you will get something different

start
d1 done
both done
d2 done

Race condition? Not at all, something entirely different – invalid use of promises. You see, done and then may sound similar but do something completely different. Done is used to callback some code once promise is done. Then is used to chain promises – it will be triggered once first promise is done and it will return entirely new promise.

Code above uses done incorrectly – when d1 is finished it calls first done, triggering d2 processing, but then immediately calls both done callback – done returns original promise to which it was applied, and since it was finished, all done callbacks are going to be called. Correct solution is as follows:

var d1 = $.Deferred();
var d2 = $.Deferred();

d2.done(function() { console.log("d2 done")});
d1.done(function() { console.log("d1 done")})
  .then(function () {
      setTimeout(function () {
        d2.resolve();
      }, 1000);
      return d2;
  })
  .done(function () {console.log("both done")});

console.log("start");
d1.resolve();

jsfiddle.net/ttuLmwxq/1/

producing output:

start
d1 done
d2 done
both done

As expected. And imagine what would happen if d2 failed to finish correctly? In first case – system would report that both were done ok. In second, it would report that d1 finished, true, but later would fail on d2 and since then all callbacks would only be triggered for fail case.

Synchronizing execution with ManualResetEvent

Yesterday I was asked a question:

We have one thread that’s starting 200 additional calculation threads. How can we synchronize execution of the main thread so that it will wait until all 200 worker threads complete?

My first answer was: use Task Parallel Library, queue 200 Tasks and Task.WaitAll() on them. Easy, straightforward and very readable. Yet that was not exactly what was expected, since using TPL was for some reason banned ;)
Well then – we have all those fancy synchronization mechanisms, why not use them? Semaphor, Monitor, ManualResetEvent, AutoResetEvent – those were my first ideas. So I was asked to explain ManualResetEvent in more details.
Then things got a little bit more awkward for me. I knew some time ago how to use them and this would give me no problem. But since time has passed by, my mind decided that implementation details are not needed any more and garbage collected. So I started explaining how I think it works. Enough said, I messed up pretty much all that was to mess up. So to make up for it I decided to blog about it.

Here we have some basic implementation:

        private static void ThreadingProc()
        {
            const int calculationsCount = 200;

            for (int i = 0; i < calculationsCount; i++)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(calculation), i);
            }

            Console.WriteLine("Calculation completed");
            Console.ReadKey();
        }

        private static void calculation(object data)
        {
            System.Threading.Thread.Sleep(100);
            Console.WriteLine("Completed calculation " + (int)data);
        }

We just fire 200 threads form ThreadPool, pass thread number to each one of them and display completion message. Each thread simulates some work and then displays its completion message as well.
Result is far from expected and looks something like this:

Calculation completed
Completed calculation 1
Completed calculation 2
Completed calculation 3
...

But what else would we expect from not synchronized parallelized execution? So let’s use ManualResetEvent to help us out.
Since our computation method can get only one parameter of object type, we will first create container class to prepare all parameters and then pass them to method:

        class TaskInfo
        {
            public int TaskId { get; set; }
            public ManualResetEvent Done { get; set; }

            public TaskInfo(int taskId, ManualResetEvent done)
            {
                this.TaskId = taskId;
                this.Done = done;
            }
        }

And then slightly modified code:

        private static void ThreadingProc()
        {
            const int calculationsCount = 200;
            ManualResetEvent[] sync = new ManualResetEvent[calculationsCount];

            for (int i = 0; i < calculationsCount; i++)
            {
                ManualResetEvent done = new ManualResetEvent(false);
                sync[i] = done;
                TaskInfo ti = new TaskInfo(i, done);
                ThreadPool.QueueUserWorkItem(new WaitCallback(calculation), ti);
            }

            WaitHandle.WaitAll(sync);

            Console.WriteLine("Calculation completed");
            Console.ReadKey();
        }

        private static void calculation(object data)
        {
            TaskInfo ti = (TaskInfo)data;
            System.Threading.Thread.Sleep(100);
            Console.WriteLine("Completed calculation " + ti.TaskId);
            ti.Done.Set();
        }

Works like a charm… Well, kind of. As you will probably notice, application will end with exception saying that WaitHandle.WaitAll can support up to 64 wait objects. That’s not going to stop us for long, does it?

            for (int i = 0; i < calculationsCount; i+=64)
            {
                WaitHandle.WaitAll(sync.Skip(i).Take(64).ToArray());
            }

This simple modification takes batches of 64 ManualResetEvents and waits for them. When they are completed, it waits for another batch and so on. Since we want to wait for all threads to complete – this give us exactly what we want with simple LINQ query.
And how would it look using TPL?

        private static void TaskProc()
        {
            const int calculationsCount = 200;
            Task[] tasks = new Task[calculationsCount];

            for (int i = 0; i < calculationsCount; i++)
			{
                tasks[i] = new Task(calculationTask, i);
                tasks[i].Start();
			}

            Task.WaitAll(tasks);
        }

        private static void calculationTask(object data)
        {
            System.Threading.Thread.Sleep(100);
            Console.WriteLine("Completed calculation " + (int)data);
        }

So quite similar, yet more readable for me. And a little faster (for 200 calculations, without console access, Tasks took about 2,5s on my machine, while ThreadPool needed 3,4s to complete) but don’t take my word on it, it was just quick mini benchmark. But mini benchmarks are fun! We all should do them sometimes just for a sake of doing them :)

Maybe this post will help someone someday. Or maybe just me in future.
See you next time!