Photon Realtime and protobuf-net serialization (without garbage collection problems)

Options
I costs me a lot of time to find a good way to use Photon Realtime with a simple to use and easy serializing framework like protobuf-net. Here are some issues that I had:
- Garbage Collection everywhere
- Slow and runtime consuming LoadBalancingClient.Service() calls
- Huge garbage creation in OpCustom
- Everything resulted in: Got a unexpected Disconnect in LoadBalancingClient State: Disconnected.

Here is my Solution:
I created a base message class that is used to register all the subclasses to photon and protobuf-net. The most important thing is, that you nest the protobuf serialization inside the photon serialization:
namespace MyGame
{
using ExitGames.Client.Photon;
using ProtoBuf;

[ProtoContract]
[ProtoInclude(1, typeof(GameInfoMessage))]
[ProtoInclude(2, typeof(ClientJoinMessage))]
[ProtoInclude(3, typeof(ClientPlayerUpdateMessage))]
//[ProtoInclude(#no, typeof(YourType))]
public class NetMessageBase
{
static NetMessageBase()
{
PhotonPeer.RegisterType(typeof(GameInfoMessage), 1, Serialize, Deserialize);
PhotonPeer.RegisterType(typeof(ClientJoinMessage), 2, Serialize, Deserialize);
PhotonPeer.RegisterType(typeof(ClientPlayerUpdateMessage), 3, Serialize, Deserialize);
//PhotonPeer.RegisterType(typeof(YourType), #no, Serialize, Deserialize);
}

private static object Deserialize(StreamBuffer inStream, short length)
{
return Serializer.Deserialize(inStream);
}

private static short Serialize(StreamBuffer outStream, object customobject)
{
var positionStart = outStream.Position;
Serializer.Serialize(outStream, customobject);
return (short)(outStream.Position - positionStart);
}
}
}

After that you simply call:
OpRaiseEvent(1, message, reliable, RaiseEventOptions.Default);
And OnEventAction you get it as a response:
(NetMessageBase)photonEvent.Parameters[ParameterCode.Data]
Hope that helps! And I hope that google takes me here if I have this problem in the future!

Comments

  • MBPPedro
    MBPPedro
    edited August 2018
    Options
    Thank you in advance for your attention. :)
  • If you're looking for a way to reduce garbage from calling LoadBalancingClient.Service() - there is a much simpler way.

    • Set LoadBalancingPeer.ReuseEventInstance to true => this is a free optimization that doesn't cost you anything or require any maintenance. It will make sure EventData is reused, rather than new'd every time.
    • Set LoadBalancingPeer.UseByteArraySlicePoolForEvents to true => this requires you to bundle all data you send in a byte[] format and send it by using a ByteArraySlice. You can read more about how that's done here: https://doc.photonengine.com/en-us/realtime/current/reference/performance-tips#serialization_usage

    Hope this helps.