Earlier today a fan of Rome2rio tweeted @rome2rio your site is super duper fast. You should blog about your trickery. That sounds like a good idea. While we don’t want to share the nitty-gritty details, we can describe three of the “tricks” we use to make Rome2rio “super duper fast”.
Autocomplete guess system
Sometimes making a system appear faster is just as effective as a real speed increase. The textbook example of this is the installation of mirrors outside elevators, so that users are distracted and the wait for the elevator seems somehow shorter.
Rome2rio’s “elevator mirror” trick is to guess a user’s search before they have finished typing their destination name. This feature was integrated into our purpose built geocoder and autocomplete technology. Unknown to most users, it gives the appearance of even faster (and sometimes almost instant) search results.
Once the user has typed in enough letters, such as the first five characters Melbo of Melbourne, our front-end assumes that Melbourne is the user’s intended search destination and quietly transmits a search request to our backend system.
If the user finishes typing Melbourne and presses enter, then the response from the earlier backend request is displayed. If the user instead types in a different destination, such as Melbot, Nepal, the assumed response is discarded and a new request to our backend system is issued.
In practice, the algorithm’s guesses are surprisingly accurate. When making a guess after the first 5 characters, the assumed destination is correct around 90% of the time.
Carefully optimized graph search
In the first couple of years developing Rome2rio, we spent considerable time carefully refining our algorithm for finding transport paths between A and B. It was important that the search algorithm was fast, typically taking less than 400ms.
The Rome2rio transport network is represented as a graph (a computer science term). Various graph search algorithms exists, however searching a multi-modal graph introduces a variety of unique complexities. For train, bus and ferry routes we closely studied several academic papers including Fast Routing in Very Large Public Transportation Networks using Transfer Pattern (2010) by Google employees.
We developed our own algorithm for assembling flight schedules into itineraries, and selected a particularly fast driving directions algorithm based on Open Street Maps data. Tying all the modes of data together, making trade-offs for travel time, cost, diversity and transfers is another component of the algorithm that we needed to develop and refine.
Everything is coded up in low level C# algorithms based on custom in-memory data structures; we avoided using out-of-the-box 3rd party system such as SQL databases for these speed critical parts of the system.
We have also invested in tools to help us analyze search performance, such as our query performance breakdown visualizer:
We’ve also experimented with different cloud hosting solutions, settling on a solution which provides very fast search performance. We are using dedicated i7-4770 machines with 32Gb of RAM provided by German based Hetzner. Since our search algorithm is largely CPU bound, these powerful boxes are perfect for our needs.
We use CloudFlare‘s reverse proxy service, which provides both a CDN for static content such as images as well as load balancing between our backend servers. Our backend machines serve queries independently from each other, whilst background processes ensure that the latest data is synced between each of them.
Finally, we rely on Pingdom to provide up time and search performance data on each of our servers.