Photon Server Serializable Data Contracts Using Reflection

I’ve recently started playing with Photon Server, working on porting some server side game logic from a Node.js server. The main appeal of Photon to me is the promise of structured, strongly typed messages and general neatness of typed code, and the ability to share definitions between the server and the client when working with a Unity3D based client. So far I’m having lots of fun, and Photon seems to deliver on it’s promise. But I’ll write about that in another post.

Photon handles message serialization using byte-object dictionaries, which results in easily deserializable messages since all fields have a fixed identifier. The Photon SDK even has a neat base class called DataContract which provides an out of the box class to dictionary serialization method.

So far is all sounds great, right? The only problem is that the DataContract class is available only for the server SDK and not for the client SDK. Reading up on their forums, the reasons for that seem to vary from not being a highly requested feature to the performance overhead in client code (namely Unity and it’s aged Mono runtime). What this means is that it’s impossible to share message definitions between the server and the client with the provided out of the box solution. Bummer!

But wait! what if I implement this feature myself? Well, turns out it’s pretty straight forward!

First of all, we need to define our own custom attribute that will be used to mark serialized fields:

Next, we’ll define a serializable to byte-object dictionary base class.
The class will feature 2 constructors – the first, a default constructor, and second a constructor that takes a byte-object dictionary and uses it to create a class instance. Additionally, we’ll add a ToParameters() method which serializes the class to a byte-object dictionary.

And the last piece of the puzzle, as you might have guessed from the definition above, is the reflective serializer.

That’s the largest piece of code in the entire setup. To sum it up in one sentence, it looks up the runtime type of the object and using reflection finds all the fields marked with the DataField attribute, and simply dumps the data in a dictionary with the key being the code specified in the attribute.

And just for completeness, here’s a sample of a serializable class implementing SerializableMapBase looks like:

Verdict Time – Does it Blend?

Being able to implement a feature only helps us as long as it actually works – but does this approach work?
The short answer is both yes and no and it really depends.

Performance wise, using reflection has marginal impact on performance, calling message.ToParameters() 100,000 times per frame in a tight loop times at ~< 0.9msec on my AMD A10, however, this generates LOTS of garbage (~37MB for the above scenario) - this in turns degrades performance greatly. However, there are several things to keep in mind - first of all, especially with regards to network serialization, you'll probably never end up serializing 100,000 messages per frame (that's 6,000,000 messages per second), second - some of the memory overhead can be optimized by creating a non-allocating serialization method and reusing the same object, however, there is still the implicit box/unboxing involved with casting value types to object which cannot be helped. To summarize - this method works for cases where the data rate is low but definitely not for tight loops and time critical segments. Think authentication, chat, stats synchronization - all of those are cases where this approach would work.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *