With web games you want hits — lot's of hits. A million per month or more if possible. Of course this means lots of traffic. While broadband became faster and cheaper during the last couple of years, traffic is still somewhat expensive. In order to get a nicer cost/income ratio there are apparently two options: reduce the costs and/or increase the income.
As you might have guessed I'm about to tackle the former with brute processing power. If you reduce the file size by 1% every 100th served file is free. With 5% it's every 20th file and with 10% every 10th file. If the price for that are only a few minutes of processing power it looks like a really good deal, doesn't it?
By the way this is the first part of a small series of articles. There will be two or three at the end, depending on how things work out. I can't really tell at this point since the required research isn't finished yet. Well, this one is the cornerstone. The follow up article(s) will extend the basic strategy outlined in this article.
The SWF file format uses ZLib streams, which are basically the same kind of Deflate streams we can see everywhere. PNG, ZIP, GZip, etc. all use Deflate for compression. If you're interested in more details on ZLib, Deflate, and GZip refer to RFC 1950, 1951, and 1952. Since the introduction of the SWF6 format almost the whole SWF file can be compressed as illustrated by the following diagram:
The first 8 bytes ("SWF H") are the essential parts of the SWF header. If compression is enabled a ZLib stream follows, which consists out of a 2 byte ZLib stream header ("Z"), the deflated data ("Deflate Stream"), and a trailing Adler32 checksum ("A32").
Unfortunately there isn't a big selection of tools to improve the compression of Deflate streams directly. However, there are a lot of nice tools for ZIP files. Ken Silverman's excellent KZIP comes to mind. It's based on the code of his PNGOUT utility, which tries really hard to squish as many bytes as possible out of PNG files.
There is also Ben Jos Walbeehm's DeflOpt utility. It optimizes Deflate streams inside of ZIP, PNG, or GZip files. However, it cannot optimize Deflate streams inside of SWF files (yet?).
That's why I went with ZIP files. It's a well-known format and there are plenty of tools available.
The ZIP file format is fortunately rather simple and reasonably well documented. The following diagram roughly illustrates the ZIP file layout:
At the very beginning is the ZIP header ("ZIP H"). Then the header of the first ZIP entry ("E1H") followed by its deflated data ("Deflate Stream"). If there are more than one file inside this ZIP another ZIP entry header ("E2H") follows and so on, but that isn't really of interest in this case since we'll only deal with a single file.
An SWF may contain other bits of deflated data inside its primary/main Deflate stream, but we'll ignore this for now. So, as far as we're concerned there is only one Deflate stream. Re-compressing it as efficient as possible requires a few steps:
Of course you can try harder by using different ZIP utilities and/or different switches, then optimizing all these Deflate streams, and using the best compressed one for the final step. (That's basically what excessive.bat does.)
|File||Old Size||New Size||Saved (bytes)||Saved (%)|
|Some random game||3,544,814||3,519,395||25,419||0.72|
swf_recompress.zip (5kb — source included)
There are two batch files: compress and excessive. The first batch will often already yield the optimal result. The second batch tries harder, but will be often unable to deliver a better result since KZIP with default block size usually yields the best result. Well, trying doesn't hurt.
Requires: KZIP, DeflOpt, and Java
Requires: KZIP, DeflOpt, Java, ZIPMIX, and 7-Zip
The savings aren't that big yet, but the next step which involves inflation of everything will increase the percentage to about 4-7% by the looks of it. But I'm actually already pretty pleased with the results so far. For example those 2.89% peeled of the YouTube player could have saved Google millions of dollars. As unbelievable as this sounds this isn't an exaggeration.