Have you noticed that you’ve been jumping into ROBLOX games quicker? That’s because our networking team has been hard at work exploring ways to make our network more stable, secure, and most importantly, fast. After a ton of experimenting, we’re pleased to report that our network is the fastest it’s ever been–our data is faster and its footprint is smaller, and we’re continuing to make tweaks and enhancements. We tapped ROBLOX Software Engineer Yunpeng Zhu to tell us how we got there.
ROBLOX has sped up dramatically thanks to a couple of changes we’ve made in our networking infrastructure. A few of these changes were very simple, while some of them became extremely complex–it’s difficult to gauge how much faster ROBLOX is running because it’s not entirely dependent on networking, but the hardware users are playing on.
In order to speed up our network data, we kept asking ourselves, “how can we push everything out from the server as fast as possible without degrading performance?” Caching and Compressing are the easy answers, but we’ll get to that.
When a player joins a game, our servers have to transfer the current state of the place to the new joining player. The server collects all the parts of the place (scripts, services, objects, etc.) and translates that information into a “bit stream” of data ready to be fired out across the internet.
We’re always working to push out more data at a faster speed from our server to our clients. The more bit stream data (network representation of objects in a game) we can cache, the less we’ll have to recreate for each newly joined player. A big development was the idea of only having to load network representation of data (like a place in ROBLOX) just once, as opposed to having to recreate bit streams every time a new player enters the game. Now, the second another player enters a game, we can re-feed the already created bit stream back to that player. Our new method of compression will allow us to do this.
Our current compression method, which we’ll refer to as the “dictionary” method, takes words and indexes and catalogs them, individually shrinking the text portion of the data in any given place. We then send the indices, instead of the words, which use less bandwidth overall.
Our dictionary plays a large role in decreasing the amount of data in a place, because it allows us to swap out long words with short numbers. If you’ve got a level with 2,000 parts, each part has several letters in their names (i.e. “smooth part”). That’s eleven characters. Multiply by that by 2,000 parts, and you’ve got a ton of data floating around. Our dictionary lets us characterize it with a number that uses far fewer characters. This drastically reduces level data payload–just using the dictionary alone, Happy Home was reduced from a 7 megabyte place to a 1.5 megabyte place.
Problem is, dictionaries aren’t synchronized across clients; they’re in flux, constantly changing as players enter games and change the environments. The number that corresponds to “Part 1” to the first player in a place is radically different than the corresponding number to “Part 1” to, say, the fifteenth person who entered the place. And because ROBLOX environments change dynamically (and because any user can change them at any given time), each user “dictionary” has similar words in it, but the words are in a different order.
We turned off dictionaries in an effort to cache all the data–doing so had two very powerful effects: On a positive note, caching all data meant we didn’t have to recreate the bit stream for each new player. On a negative note, lack of compression made the size of our game data way too large–no compression whatsoever means our servers would have to send entire entries in every instant, every time a new player joined the game. This would require an unreasonably high amount of bandwidth.