Mobile clients - performance suggestions?

Started by
21 comments, last by lerno 12 years ago
I don't really like the performance I'm getting when running my mobile client against my game server. Any general suggestions to improve performance (I'm using TCP) aside from setting TCP_NODELAY?

What sort of roundtrip time should I expect as a minimum for reasonably small packets?

There are usually not much data sent, but when the player quickly navigates on the map, they might be sending several move actions a second. Without TCP_NODELAY, I obviously get problems, with lots of commands bundled together, but even without Nagle I occasionally get the results from the server in bursts. (This might be from some unrelated bug, but I don't see it running in the simulator)
Advertisement
How much data are you sending, how frequently, and over what kind of connection? For example, perhaps you are sending 20 to 45 byte chunks, and trying to do it 5 times per second, over a 3G phone connection and TCP.

Most network performance issues are a combination of bandwidth and latency, with a bit of error correction thrown in for good measure. Knowing your actual communications pattern is essential to give advice about how to improve it.
Frequency depends linearly on player input. If the player takes more actions, data is sent more often. The action where the user has the most chance of sending data packets is when walking on the world map, since there is an input and return data every time this happens. Now I can hide this latency somewhat, but I figure the better I can make it before hiding the latency, the better.

The user inputs something like 40 bytes, receives 90 bytes back for each move. I think the maximum is like 5 times a second, when the user tries to walk as fast as possible.
hey, i am currently working on the same stuff. maybe you want to exchange some knowledge? write me a pm if you'd like!

p.s. how are you connecting to the server? what device are you using? in what language and with what libs is the server coded? Can you give us more background information?

I open sourced my C++/iOS OpenGL 2D RPG engine :-)



See my blog: (Tutorials and GameDev)


[size=2]http://howtomakeitin....wordpress.com/

with lots of commands bundled together[/quote]

This will happen for all networking, but especially for mobile networking, where noisy environments are a fact of life, and occasional packet drops cause coalescing in re-transmission. Your stream-level protocol needs to deal with figuring out where messages begin/end, and also needs to deal with messages possibly arriving cut in half (first the first half, then the second half.)

Regarding the "burstiness" of connections, that's what you get on TCP over a noisy connection. There are two possible "fixes:"
1) Open more than one TCP connection, and multiplex messages across them (say, round-robin.) This is complex, and only gives you some amount of improvement; a "noise transient" event in the environment may very well end up stalling/re-transmitting all of those connections.
2) Switch to UDP. When packets get there, they get there, and you don't have to wait for earlier packets to get later packets. The link layer may re-transmit and re-order packets; the easiest thing to do is to number each packet and drop any packet that has a lower number than the previously received highest-numbered packet. The draw-back is that, well, packets will be dropped!
enum Bool { True, False, FileNotFound };

p.s. how are you connecting to the server? what device are you using? in what language and with what libs is the server coded? Can you give us more background information?


In order:

- Plain sockets
- iPhone/iPad
- Server in java, POJO NIO
- What else are you interested in?

with lots of commands bundled together

This will happen for all networking, but especially for mobile networking, where noisy environments are a fact of life, and occasional packet drops cause coalescing in re-transmission. Your stream-level protocol needs to deal with figuring out where messages begin/end, and also needs to deal with messages possibly arriving cut in half (first the first half, then the second half.)
[/quote]

I use a simple 2 byte header for the packet length, followed by the packet payload.


Regarding the "burstiness" of connections, that's what you get on TCP over a noisy connection. There are two possible "fixes:"
1) Open more than one TCP connection, and multiplex messages across them (say, round-robin.) This is complex, and only gives you some amount of improvement; a "noise transient" event in the environment may very well end up stalling/re-transmitting all of those connections.
[/quote]

That sounds like it would end up rather complex?


2) Switch to UDP. When packets get there, they get there, and you don't have to wait for earlier packets to get later packets. The link layer may re-transmit and re-order packets; the easiest thing to do is to number each packet and drop any packet that has a lower number than the previously received highest-numbered packet. The draw-back is that, well, packets will be dropped!
[/quote]

Dropping packets is probably not ok since the current model relies on all updates going through. There is no redundancy in that the same values are repeatedly updated / sent. I read about that neat UDP-trick they used in X-Wing vs. Tie Fighter, where each UDP-packet also contained the data of the previous packet. If both packets disappeared, that was usually indicative of serious connection problems. I suppose one could work around it by enforcing a resend in those cases.

BUT, rewriting server with UDP instead of TCP is nothing I'd like to do unless I'm forced. Most likely I'll simply hide the latency in graphics transitions instead.

There are no other tricks I could employ?

There are no other tricks I could employ?

Small messages like that tend to get clumped together, as was mentioned.

You could try sending larger messages. Even if the messages are full of empty padding, they are less likely to get queued by various network hardware.

But ultimately you are at the mercy of the network. You cannot control the timeliness of messages.

You could try sending larger messages. Even if the messages are full of empty padding, they are less likely to get queued by various network hardware.



Personally, I'd like to see some persuasive data about this before I went to such drastic measures. I don't believe this would help, and on crowded networks (WiFi, 4G, etc) using more bandwidth *will* hurt overall latency.

enum Bool { True, False, FileNotFound };

Small messages like that tend to get clumped together, as was mentioned.

You could try sending larger messages. Even if the messages are full of empty padding, they are less likely to get queued by various network hardware.

But ultimately you are at the mercy of the network. You cannot control the timeliness of messages.


Actually, I already tried that (sort of). My initial version sent a cascade of separate update packets. Bundling them together for a larger direct write didn't do anything. Not unsurprisingly perhaps, given that I'm using TCP and just pushing packets asynchronously.

This topic is closed to new replies.

Advertisement