Compression is not a UI Decision

May 12, 2009

One of the dilemmas that any software designer goes through is determining in which subsystem a particular behavior needs to be implemented and whether it should be user configurable or not. By user, I don't necessarily mean the only end user; in the case of plugins or server software, I also refer to the people installing / configuring the plugin or software.

I've been pondering this question after I ran into horrendous performance issues with a Wordpress theme I used for my imagery blog, which uses shared hosting. A theme, for those not aware, is the UI customization that can be applied to a piece of software to change its look and feel - there's no added functionality provided i.e. they're not plugins. The theme in question is Grain - a plugin specific theme, it requires Yet Another Photo Blog. When using the specific theme for YAPB, the pages would take about 16-17 seconds to render. Since I had to put both the theme and the plugin into service at the same time, it took me some time to figure out where the problem lay.

After some head scratching, I replaced the Grain theme with another YAPB compatible theme and the pages began rendering in the standard 2-3 seconds as before. So, definitely a problem with the theme. I visited other sites, including the theme author's that used the Grain theme. They rendered pretty fast i.e. in under 2 seconds. So, something was off with my config. But what? There were a number of places things could go wrong. Step 1: would be to use wget (such a sweet tool) to retrieve a imagery blog page. Page came back in 1-2 seconds. So, it seemed it was not a problem with the page itself. Step 2: Was it problem with the browser? Firefox is my default. So, I tried with IE. No dice. Still the same 16-17 seconds to render a page. What do browsers do that wget does not? They send headers automatically.

Great - time for step 3: look into the browser headers. I installed the Web developer plugin for Firefox. Yes, I know. Shame on me for not having it installed already. Then I got YSlow. Awesome debugging aid. Turns out it was the page itself that was taking up almost all of the 16-17 seconds. Examine the headers - request and response headers look normal. The browser accepts gzipped and deflated content and the server was sending back gzipped content. Except, the compressed content was larger than the uncompressed content. Hmmm, that's odd. HTML compresses very well due to repeated patterns, so something was definitely off. The one time that content increases in size when compressed, is if it's already been compressed - which is why one never compresses .jpg, .gif or .png files. Those formats are compressed internally. So, was there double compression going on? If so, how the browsers were able to double decompress is still a bit of a mystery to me, but that part was definitely working. IE doesn't have any option to turn off compression. There's the sledgehammer of disabling HTTP 1.1, but that's overkill. So, I continued w/ Firefox. You can change many, many options by typing about:config in the address bar. I disabled compressed content acceptance and viola - the imagery blog pages began rendering within 2-3 seconds.

Step 4: Time to revert the Firefox setting and start fiddling with the server. Easiest thing to do was disable compression for the imagery blog using .htaccess - my imagery blog is on a shared host using Linux / Apache. So, I proceeded to do what seemed to be the obvious, viz. add the following lines to the .htaccess file of my imagery blog:

<ifModule mod_gzip.c>
    mod_gzip_on No

But, that didn't work. So, hunted for another solution, which was to use rewrite rules to disable gzip, to be added in the mod_rewrite.c section:

    RewriteRule . - [E=no-gzip:1]

No, dice again. I had also added the following mod_expires section based on YSlow recommendation and those changes were getting picked up when I looked at the response headers:

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 seconds"
    ExpiresByType text/html "access plus 1 seconds"
    ExpiresByType image/gif "access plus 2592000 seconds"
    ExpiresByType image/jpeg "access plus 2592000 seconds"
    ExpiresByType image/png "access plus 2592000 seconds"
    ExpiresByType text/css "access plus 604800 seconds"
    ExpiresByType text/javascript "access plus 216000 seconds"
    ExpiresByType application/x-javascript "access plus 216000 seconds"

Hmmm. Something else which was doing the compression was slowing things down. Step 5: A search for php compression revealed that there was support for compression available in the standard php libraries. Bingo! Grepping for the use of php compression showed a function in the theme that enabled it if there was support available and if the (system wide) php.ini file had it enabled. Ouch! Therein lay the issue. I couldn't muck with the system wide php.ini file, since I was on a shared host. Php compression was slow, not sure why, but it was SLOW. There were no configuration options to disable php compression in the theme. So, the only way to do it was to modify the source code. I commented out a few lines to disable php compression and viola, everything worked fine thereafter.

This was quite a hassle. The major lesson here is that compression is not a UI component decision: The biggest offender here in this debacle is the Grain theme designer. Whether to use compression is not a decision for a UI component to make. Essentially, the software designer overstepped his/her bounds. While, s/he may have added compression with the best interests and keeping mind scenarios that s/he had encountered, the decision was definitely wrong.

Last modified 3 years ago Last modified on Feb 18, 2016, 4:48:23 PM