In this entry, I will try to explain some of the steps I’ve made to optimize the performance of the tower war tracker. I won’t cover all the details; But I’ll try to communicate the general idea of it all. Warning: Technobabble ahead!
Why pregenerated dynamic content is important
The tower war tracker might look quite innocent at a first glance, but it’s really a giant beast. As an example, generating the full data set used by the SideXP graph (seen here) takes about 5 minutes. I’ll go into detail on why later. Naturally, this is something which is done at predefined periods, the result is stored, and clients receive a pregenerated data set.
There’s quite a few bits of information which are less time-consuming but still costy to produce. Two examples would be the “longest standing sites” and “TL7 Tower Status” (seen here). Let’s take a closer look at the TL7 tower status: It will query the database for a list of active tower sites for the given dimension (Atlantean or Rimor), then iterate this list. For each site, it will query the database about last victory and last attack involving the site. If there’s no tower attacks after the last victory against the site, the tracker doesn’t know for sure who owns the site; and will apply some “magic” to generate an educated guess. These guesses will show up as “???” with the appropriate color.
This is why the SideXP graph is insanely expensive: It will repeat this process with an extra parameter: “Who owned the sites at specified time”, where the specified time is incremented by 6 hours for every iteration. With over 5 years of history on Rimor, that’s about 7300 iterations. With roughly 260 active tower sites, it will do the “who owns this site” check 7300 * 260 = 1 898 000 times. That’s a lot of querying!
Serving content as quickly as possible
The tower war tracker will give your browser a rather simple content-less HTML page, which only have the layout and some knobs to be used by the sites scrips to fill in the real content. This makes it possible to tell your browser to keep the layout in cache for quite a long time, since it virtually never changes. This makes page navigation seem virtually instant after the first visit.
The site script will launch multiple parallel queries in the background, asking the web server for information; i.e. the content which will be placed at various places on the webpage. This model allows for faster delivery of content, because the web server can work on generating different parts of the content at the same time instead of in sequence. To illustrate the point: If it was all to be generated in sequence, it would be something like this: “Tower Owners” (400ms), “Misc Stats” (600ms), “Attacks” (300ms), “Victories” (300ms); A total of 1600ms (or 1.6 seconds).
When it’s done in parallell, it can do all of those groups at the same time. Let’s add in a 10% overhead due to it requireing more connections, and we end up with the longest request of 600ms + 10% = 660ms (or 0.66 seconds); That’s a 59% time reduction!
Further, by splitting up the requests like this, the reverse proxy which is sitting in front of the web server is able to hang on to some content (let’s say, the “longest standing sites”) for a longer period of time than more dynamic content, such as recent attacks. This means the reverse proxy can serve already generated content when a user request it, instead of constantly poking the web server for every piece of content. This results in overall better response times.
The new model
Seeing some performance benchmarks of the website, there’s quite a bit of delay between initial connection and the actual content being served; Even for static content. This is something I’m going to help amend by exposing the reverse proxy directly to the internet instead of hiding it behind medicore firewall hardware. I will explore the possibility of making the reverse proxy serve static content directly, as well as moving the reverse proxy to new hardware which should boost disk-to-network transfer performance.