Fast text parser for server-client messages - MMO

1.2k views Asked by At

Application

I am working on an MMO and have run into an issue. The MMO server I've built is fast and locally sending messages to my game client every ~50 milliseconds on UDP sockets. Here is an example of a message from sever to client through my current message system:

count={2}body={[t={agt}id={42231}pos={[50.40142117456183,146.3123192153775]}rot={200.0},t={agt}id={4946}pos={[65.83051652925558,495.25839757504866]}rot={187.0}}

count={2}, 2 = number of objects
[,] = array of objects

I built a simple text parser, code: http://tinypaste.com/af3fb928

I use the message like :

    int objects = int.Parse(UTL.Parser.DecodeMessage("count", message));
    string body = UTL.Parser.DecodeMessage("body", message);
    for (int i = 0; i < objects; i++)
    {
        string objectStr = UTL.Parser.DecodeMessage("[" + i + "]", body);
        // parse objecStr with UTL.Parser.DecodeMessage to extract pos & rot and apply to objects
    )

Issue

When I have more objects ~ 60+ the performance dramatically decreases.

Question

What is standard method for packaging and reading message between clients and server in MMOs or real-time online games?

3

There are 3 answers

0
vgru On BEST ANSWER

One of your problems might be unnecessary string instantiation. Any time you do a concatenation, split, or get a substring, you are creating new string instances on the stack, which are copied from the original string and need to be collected afterwards.

Try to change your code to iterate through the string character by character, and parse the data using the original string only. You should only use indexing, indexOf and possibly even write your own int and float parsers which accept a string offset + length to avoid creating substrings at all. I am not sure if this is overkill, but it's not "premature" optimization if you have hard evidence that it works slow.

Also, did you try Protocol buffers? I believe their performance should be pretty good (just write a small console app for benchmark). Or with JSON, that's a standard concise format (but I have no clue about how optimized Json.NET is). Nothing should usually beat a hard coded specialized parser in terms of performance, but with future maintenance in mind, I would try one of these protocols before anything else.

0
tzaman On

I'd look into using an RPC framework like Thrift to do the lifting for you. It'll do the packing and parsing for you, and send stuff over the wire in binary so it's more efficient.

There are a bunch of other options, too. Here is a comparison of some.

0
JulianR On

A binary protocol would be a lot faster here. Take the coordinates that you pass in for example. When you transport those as bytes, they will take up 8 bytes per axis, whereas the string representation uses 2 bytes per character (unless you transport as ASCII but even then a binary double would be smaller).

Then actually turning that string into a number is a lot more work; first a substring has to be created, incurring garbage collection overhead later on, the number has to be parsed which isn't fast (but to be fair, you can still parse hundreds of thousands of doubles a second) because .NET's double.Parse is very general and has to accommodate a lot of different formats. You would gain noticeable speed by writing your own double parser in case you stick with text, but like I said, you ought to go with binary if message parsing is a bottleneck. Turning bytes into doubles (with a little bit of unsafe magic, which should be fine if you're running a server and should have Full Trust mode) is a matter of copying 8 bytes.

If your messages are mostly just coordinates and such, I think you could gain a lot by creating your own binary format.