Image by Richard Parmiter via Flickr
Saturday, February 28, 2009
Ranting about password strength
Reducing Page Load Time on Google App Engine Pages With Multiple JavaScripts
While I was creating Conquer-on-Contact I was annoyed to find out the game's initial load times were very high. Some of this is just because App Engine's performance is damn inconsistent from minute-to-minute, but a look at Firebug's Net tab revealed something shocking:
Oh my word Firefox, what are you doing? Serial downloading in 2009? Here is the offending code:
<script type="text/javascript" src="/js/jquery.js"></script> <script type="text/javascript" src="/js_min/jquery_form.js"></script> <script type="text/javascript" src="/js_min/jquery_countDown.js"></script> <script type="text/javascript" src="/js_min/jquery_color.js"></script> <script type="text/javascript" src="/js_min/jquery_pulse.js"></script> <script type="text/javascript" src="/js_/conquer-on-contact.js"></script>
After some Googling I found that IE8 loads scripts in parallel automatically but for some reason Firefox 3.0 is still in the dark ages. This MSDN blog entry is helpful, but I don't really want a hacky client-side solution.
What's the best way to solve this, then? Well, we could combine all the javascript files manually, but this makes them a pain to edit. I don't need to be messing around with jquery.js when I am just trying to use the library.
So why not keep them as separate files but combine them server-side when serving? This will waste some cpu but we can minimize that by caching the results for at least an hour. I set it up starting with some automatic javascript minification code written by Austin Chau. Add something like this to Austin's javascript.py (but change the filenames to fit your own javascripts!):
class JsAgg(webapp.RequestHandler):
def get(self):
data = memcache.get(key="JSAGG")
if data is None:
filenames = ["js/jquery.js",
"js/jquery_form.js",
"js/jquery_countDown.js",
"js/jquery_color.js",
"js/jquery_pulse.js",
"js/conquer-on-contact.js"]
data = ""
for filename in filenames:
data += minify(filename) + '\n'
memcache.add(key="JSAGG", value=data, time=memCacheExpire)
self.response.headers['Content-Type'] = 'text/javascript'
self.response.out.write(data)
...
# serving minified/aggregated javascript from mem cache
apps_binding.append(('/js_agg/', JsAgg))
[Download the modified javascript.py]
Now change the JavaScript loader in your html:
<script type="text/javascript" src="/js_agg/"></script>
So what does the page load profile look like now?
Of course we are getting screwed by Google Analytics now but you can see the critical change: We went from about 1.1s to load all the Javascript down to about 250ms.
It might be a good idea to add the other handlers (serve aggregated from disk, don't minify, etc) as well but I leave that as an exercise for you.
Some have suggested it would be better to access JQuery via Google's dedicated CDN. I agree this is a better choice, but only once all the major browsers get their act together as far as script loading is concerned.
Friday, February 27, 2009
Conquer-on-Contact released!
I've just released Conquer-on-Contact, a simple multiplayer strategy game. This is nothing to write home about, just a chance for me to learn jQuery and get a better feel for the performance characteristics of App Engine's Datastore. Here's the blurb:
Finally, a chance to put your spreadsheet skills to productive use! Move your cell around the grid while avoiding other players. Collect bonuses to AUGMENT your cell army. Once you have achieved ULTIMATE SIZE, move into another player's cell to CONQUER them. REVEL as you finally declare victory over the spreadsheet. Just don't tell any of your friends; they'll make fun of you behind your back for weeks afterwards. |
Wednesday, February 18, 2009
The Wisdom Of Cross-training
Lately I've been considering the value of developing talents in multiple key areas rather than focusing everything on specialization. Truth is, most people I know prefer to specialize. They say, "Oh yeah, I'm an FPGA guy," and they identify with that as their primary skill rather than broadening their horizons and asking, "what skills would compliment this one in a unique and useful way?" And that's the key, you ideally want to develop complementary skills that:
- Not a lot of other people have
- Compliment each other and are useful together
If it's a job you're after, then you have to make sure you market yourself correctly once you've picked the right combo. For example, consider a computer programmer who is excellent at public speaking and interacting with customers to determine their needs. It's a rare combo that could be extremely valuable to the right company, but most would be glad to just stick him in a cube and be done with it. So he'd need to pay attention, communicate his strengths, and pick a position with a company that understood his value.
So what are some rare and useful combinations, and how could you use them to your advantage? Here are some suggestions. Can you think of others?
- Direct Marketing + Software Development: Design a wizard that allows people to present customized marketing content based on known information about a user, the keyword a user was searching for, etc, to create a tailored experience for each prospect.
- Web Design + Creative Writing: Design an attractive new portal for presenting fiction online. Think Amazon.com eBook reader that doesn't look and feel like it was designed by a brainless monkey.
- UI Design Principles + Hardware & Electronics Fabrication: This is how you create an iPod, iPhone, Kindle, etc... Except you should aim for a device that doesn't already have a super-chic high-end version, like maybe the handheld home electricity meter, a device that's only going to become more popular in the coming years.
