October 2013 - Alessandro Alinone's talk at HTML5 Developer Conference (Moscone Center, San Francisco)
VIDEO OF THE TALK:
https://www.youtube.com/watch?v=cSEx3mhsoHg
ABSTRACT:
The advent of WebSockets has made it easier to develop HTML5 multiplayer games and real-time collaboration tools. But WebSockets are just a transport, upon which a full stack of abstractions and optimizations needs to be built. The goal is the reduction of network bandwidth and latency, together with the possibility to use high-level constructs and paradigms, to lower the development effort and increase the robustness of the application.
In this session, Alessandro will explain and demonstrate how some optimization techniques, originally developed for the financial services industry in the last decade, can be applied to HTML5 gaming and collaboration.
More information on this topic is available in this article: http://blog.lightstreamer.com/2013/10/optimizing-multiplayer-3d-game.html
GITHUB PROJECTS:
Chat-Tile Demo:
- https://github.com/Weswit/Lightstreamer-example-ChatTile-client-javascript
- https://github.com/Weswit/Lightstreamer-example-ChatTile-adapter-java
Room-Ball Demo:
- https://github.com/Weswit/Lightstreamer-example-RoomBall-client-javascript
- https://github.com/Weswit/Lightstreamer-example-RoomBall-adapter-java
Super Mario Demo:
- https://github.com/Weswit/Lightstreamer-example-FullScreenMario-client-javascript
- https://github.com/Weswit/Lightstreamer-example-FullScreenMario-adapter-java
3D World Demo:
- https://github.com/Weswit/Lightstreamer-example-3DWorld-client-javascript
- https://github.com/Weswit/Lightstreamer-example-3DWorld-adapter-java
More Than Just WebSockets for Real-Time Multiplayer Games and Collaboration
1. More Than Just WebSockets for
Real-Time Multiplayer Games and
Collaboration
Alessandro Alinone
CTO, Lightstreamer
HTML5 Dev Conf
San Francisco / 2013-10-22
2. Cool, I bet you have already played with them.
With WS you unleash the power of real-time
bi-directional communication in the browser.
But WS are just a transport layer, which makes
it extremely easy to clutter the network.
WS might not be enough to make your new
HTML5-amazingly-real-time app take off...
WebSockets?
3. You need a full stack of abstractions over WS,
to:
1. Optimize the traffic (reduce bandwidth
and latency)
2. Simplify code development and increase
code robustness, by using higher-level
constructs and paradigms
So, what?
4. Can we reuse the mechanisms originated for
financial trading apps and apply them to
HTML5 gaming and collaboration?
You bet!
Idea
8. Check out the game loop...
onItemUpdate: function(upd) {
var x = upd.getValue("posX");
if (x !== null) {
this.avatar.style.left = (x-(this.avatar.offsetWidth/2))+"px";
this.posX = x;
}
var y = upd.getValue("posY")
if (y !== null) {
this.avatar.style.top = (y-(this.avatar.offsetHeight/2))+"px";
this.posY = y;
}
}
Even if the physics of interaction among many objects is
pretty complex, the client simply has to move some divs
to the given coordinates (full offloading of the physics to
the server).
9. Multiplayer Games: Pure Server-side Mode
Positions
Commands
Positions
● Physics runs on server side only
● Stream of user commands from clients to server
● Broadcast of position updates from server to clients
● Clients are pure renderer, with no prediction and no
interpolation
Real-Time
Server
Client
(HTML5 Browser)Commands
Client
(HTML5 Browser)
Client
(HTML5 Browser)
Positions
Commands
Commands = user input
(key press, joystick move,
device tilt, accelerometer,
etc.)
Positions = current position
of each object (coordinates,
quaternions, etc.)
sim
plified
view
10. Others'Commands
Commands
Others'Commands
● Physics runs on the client side only
● Stream of user commands from clients to server
● Broadcast of all users' commands from server to clients
● Each client calculates the world independently
Real-Time
Server
Client
(HTML5 Browser)Commands
Client
(HTML5 Browser)
Client
(HTML5 Browser)
Others'Commands
Commands
Commands = user input
(key press, joystick move,
device tilt, accelerometer,
etc.)
Others' Commands =
commands originated from
all other players
sim
plified
view
Multiplayer Games: Pure Client-side Mode
11. Multiplayer Games: Hybrid Mode
Others'Commands
Commands
Others'Commands
● Physics runs on both server and client side
● Stream of user commands from clients to server
● Broadcast of all users' commands from server to clients
● Periodic broadcast of position updates from server to cl.
● Each client calculates the world and resyncs with
authoritative server
Real-Time
Server
Client
(HTML5 Browser)
Commands Client
(HTML5 Browser)
Client
(HTML5 Browser)
Others'Commands
Commands
Commands = user input
(key press, joystick move,
device tilt, accelerometer,
etc.)
Others' Commands =
commands originated from
all other players
Low-Freq Positions =
periodic updates of object
positions
sim
plified
view
Low-freqPositions
Low-freqPositions
Low-freqPositions
12. Pure server-side mode
Cons: potentially high bandwidth; animations subjected to
network latency and congestion
Pros: much simpler client code; cheaper client hardware
Pure client-side mode
Cons: worlds can diverge; complexity to align initial state
Pros: smoother and more reactive animations
Hybrid mode
Cons: more complex to implement
Pros: the best of two modes; client prediction and
interpolation can be used
13. Pros of TCP:
● Reliable (in-order guaranteed delivery)
● If Web protocols are used, can pass through proxies
and firewalls
Cons of TCP:
● Retransmissions... If a segment is lost, newer data
queues up in the server buffers until the initial
segment is actually delivered. This provokes a clutter
on the network, as bursts of aged data are sent out,
with the risk of triggering a continuous packet loss on
small-bandwidth networks.
TCP vs. UDP
14. A high-frequency stream of real-time data can be handled
by a streaming server via queuing or resampling.
In many cases, not all the data samples are needed. With
resampling, the amount of data is reduced. Receiving less
frequent updates does not mean receiving old updates.
Resampling a real-time data flow is a procedure that
needs to take several variables as input:
● unsampled data flow
● desired maximum frequency
● desired maximum bandwidth
● currently available bandwidth
Data Resampling
15. ● Bandwidth allocation: For each client, max bandwidth
allocated to its multiplexed stream connection.
Allocation can be changed on the fly.
● Frequency allocation: For each data flow of each
client's multiplexed stream connection, max update
rate can be allocated. Allocation can be changed on
the fly.
● Real bandwidth detection: Internet congestions are
detected and the server continuously adapt to the
currently available bandwidth.
The streaming server should heuristically combine these
three categories of information to dynamically throttle
the data flow applying resampling.
Dynamic Throttling
16. Instead of simply discarding updates, when resampling is
done, the sender should try to merge them to save as
much information as possible.
Example:
Event 1: X=5.1; Y=3.0; Z=2.3
Event 2: X=unchanged; Y=3.1; Z=2.5
Event 3: X=5.3; Y=unchanged; Z=2.8
If the resampling algorithms decides to drop event 2, the conflation
mechanism will produce a single update, merging 2 and 3:
Conflated event (2-3): X=5.3; Y=3.1; Z=2.8
Conflation
17. Disable Nagle's algorithm (TCP_NODELAY).
Pack updates efficiently into TCP segments.
What is the maximum latency you can accept to forge
bigger TCP segments and decrease the overheads (both
network overheads and CPU overheads)?
The highest the acceptable latency, the more data can be
stuffed into the same TCP segment (batching), increasing
overall performance.
Batching
18. Now please go to:
bit.ly/mor777
(better with Chrome)
19. We took the HTML5 version on Super Mario Bros. and
made it multiplayer in a few hours... (it's not perfect, but
gives an idea).
Thanks to Josh Goldberg for creating the HTML5 version of Mario!
20. triggers.js
function keydown(event) {
...
lsSendUserUpdate(event, 0); // Send key press event to Lightstreamer
}
function keyup(event) {
...
lsSendUserUpdate(event, 1); // Send key press event to Lightstreamer
}
function lsSendUserUpdate(key, upOrDown) {
lsClient.sendMessage(key + "|" + upOrDown + "|" + mario.left + "|" +
mario.top + "|" + mario.power + "|" + gamescreen.left + "|" +
gamescreen.top + "|" + currentmap[0] + "|" + currentmap[1] + "|"
+ area.setting, userGuid);
}
Sending local Mario's commands to the server
(and piggybacking positions to correct drifts)
21. Receiving remote Marios' commands from the server
maps.js
lsSubscription.addListener({
onItemUpdate: function(updateInfo) {
try {
var user = updateInfo.getValue("key");
var status = updateInfo.getValue("command");
switch (status) {
case "ADD":
lsProcessAddUser(user); break;
case "DELETE":
lsProcessDeleteUser(user); break;
case "UPDATE":
lsProcessUpdateUser(user, updateInfo); break;
}
} catch (e) { log(e); }
}
});
22. maps.js
function lsProcessUpdateUser(user, updateInfo) {
...
var mario = window.otherMarios[user];
...
setLeft(mario, updateInfo.getValue("xLoc") + ...);
setLeft(mario, updateInfo.getValue("yLoc") + ...);
...
var involvedKey = parseInt(updateInfo.getValue("involvedKey"));
var upOrDown = parseInt(updateInfo.getValue("upOrDown"));
switch (upOrDown) {
case 0:
handleKeyDownUpdate(mario, involvedKey); break;
case 1:
handleKeyUpUpdate(mario, involvedKey); break;
}
Managing remote Marios' commands
(together with piggybacked positions to correct drifts)
23. Delta Delivery
Lightweight Messages
Instead of sending a full world snapshot at each update,
send only the actual changes (delta) since the last update.
Full snapshots are sent only at client startup and after
disconnections.
Avoid verbose data representations such as XML and
JSON, which carry redundant metadata (field names) with
each update.
Go for lightweight representations, such as position
based, to reduce message size.
24. Automatic Detection of Best Transport
There are still many cases in the real world where
WebSockets are blocked by network intermediaries.
Automatic and fast fall-back on a per-connection basis, to
reach all clients.
WebSocket
HTTP Streaming
HTTP Smart Polling
WebSocket
HTTP Streaming
25. Contrary to common belief, the real advantage of WS over
HTTP Streaming is in client-to-server messaging.
Implement ordering, acknowledge, retransmissions, and
baching even over HTTP, to reach all clients.
Client-to-server In-order Guaranteed
Message Delivery
ServerBrowser ServerBrowser ServerBrowser
TCP connection 1 TCP connection 1 TCP connection 2
WebSocket
HTTP
28. You need a publish-subscribe paradigm to govern which
messages should be delivered to which clients.
With asymmetric pub-sub, the subscribers are on the
client side and the publishers are on the server-side.
Clients send messages to the publishers, which use them
to create the actual messages to publish.
Message Routing
Data Adapter Client
Publisher Subscriber
sendMessage
29. Subscriptions should be based on items and schemas
(sets of fields)
Item: object5 - Fields: "posX", "posY", "posZ", "rotX", "rotY", "rotZ", "rotW"
Every client can subscribe to as many items it needs, each
with its own schema:
As a result, a multiplexed stream should be created:
Subscription Model
Client
subscribes
Field "A"
Item1
Field "B"
Field "C"
Field "X"
Item2
Field "Y"
Field "A"
Item3
Field "X"
Field "C"
Field "Y"
Clientdelivers Item 1
snapshot
Item 1
update 1
Item 2
snapshot
Item 1
update 2
Item 2
update 1
30. With the item-based approach, all the routing scenarios
can be supported: broadcast, multicast, and unicast.
Massive fan-out and individual messaging should be
supported on the top of the same physical connections.
Content-aware subscription modes can optimized data
based on their semantics.
Multiple Routing Scenarios
publishes
Item 1
publishes
Item 1
(once)
Data Adapter
Client 1,000,000
Client 1
... Massive fan-out,
broadcast
Data Adapter
Client 2
Client 1
publishes
Item 2
item 1
item 1
item 1
item 2
Personal messages,
unicast
31. Of course, your server needs to scale a lot to manage the
real-time data for massively multiplayer online games.
● Use a concurrent staged-event driven architecture
with non-blocking I/O.
● Automatically tune your thread pools based on the
number of CPU cores.
● Enable graceful degradation.
● Support horizontal scalability via clustering.
Results we got for a single server instance:
● One million clients, with a low message rate on each connection (a few
updates per minute per client).
● Tens of thousands clients, with tens of messages per second per client.
Scalability
32. Commercial time :)
Lightstreamer implements all the discussed techniques
and much more!
It's not open source, but free editions are available and we
have a Startup Program to help new entrepreneurs.
With 13 years of continuous evolution, it is the most
widespread solution in the finance industry, now
conquering several other verticals.
33. Links
Contact me
- alessandro.alinone@lightstreamer.com
- @alinone
Optimizing Multiplayer 3D Game Synchronization Over the Web
http://blog.lightstreamer.com/2013/10/optimizing-multiplayer-3d-game.html
3D World Demo
http://demos.lightstreamer.com/3DWorldDemo