About Humans, Horses, and Taxes

This morning I reread my previous post about optimizing cross-compiled JavaScript and I noticed that I didn’t quite tell the whole story. There is a different, almost philosophical, angle that I would like to share with you. Many readers might have walked away with the impression that I am just a “static type-guy” while the future will be dominated by “dynamic” languages like JavaScript and Dart. It is true that at this point I prefer static types – but really solely for pragmatic reasons. My explanation will take you to some strange places…

 

The Illusion of Life

Let me state the obvious: You are now staring at your computer screen. What you are looking at are not real buttons and the objects moving in your game are not really alive. You have been tricked and you like it that way. It’s all an illusion! A good app keeps those illusions alive and sucks you in, a bad app ruins your buzz and makes you painfully aware of the fact that you are just staring at a computer screen. But what is the secret sauce of those illusions? I think, that the main ingredient of that sauce is processing velocity, which needs to be just powerful enough to satisfy a few “human constants”.

 

Acceptable Frame Rates

I know from my own experience that a game crawling at 6 frames per seconds (fps) does not do the trick. It does not suck you in, instead you look at the game and think: Oh, yeah, this is some game on my screen. The illusion is broken. So what is the “acceptable frame rate” when moving pictures come to life? Here at Adobe we aim for 20fps, but sometimes that’s just not doable. It seems that 16fps is the absolute minimum. Everything under 16fps ruins your buzz. Perhaps we can then just say:

20 frames per second = 1/20 seconds per frame = 50ms per frame
50ms >= processing velocity

 

Acceptable Response Time

I couldn’t find any literature on “acceptable frame rates” but there is a lot of material out there that discusses “acceptable response times” for web applications. According to this article  Miller (1968) and Card et al. (1991) summarize acceptable response times as follows:

  • 100 ms is about the limit for having the user feel that the system is reacting instantaneously.
  • 1.0 second is about the limit for the user’s flow of thought to stay uninterrupted, even though the user will notice the delay.
  • 10 seconds is about the limit for keeping the user’s attention focused on the dialogue.

In my opinion users become impatient in these days if they don’t get any visual feedback with some kind of progress report after the 1.0 second mark. If your desktop app is not up and running after 10 seconds you have lost the user, or made her angry about your product and, in extension, to your company. Also, I estimate that the average attention span for launch times is much shorter for mobile apps. I am afraid, your app needs to be up in about 1 second on mobile devices or the buzz is ruined. It seems that for button clicks we can assume:

100 ms >= processing velocity

and for launch times, which includes load times, we should be on the safe side with:

1 s >= processing velocity

 

Three of a Perfect Pair

(UPDATE, 2/13/2012: I corrected the formula. It’s SW/HW not HW/SW. The bigger the tax, the greater the expression, which needs to be smaller than the Human Constant on the left hand side.)

It seems that there are some human constants (20 fps frame rate, 100 ms click response, 1 s launch time) that set the performance rules every app has to obey. I would define “processing velocity” as the hardware’s ability to process software as fast as possible. If you adopt this definition then hardware has the horsepower while software is the sticky part you throw into the blender. We could generalize this relationship as follows:

Human Constant >= (Software Tax) / (Hardware Horsepower)

This crude formula describes for me perfectly that equilibrium, which must stay in balance, or your app will suck. Your JavaScript can be inefficient and bloated (high software tax). But if the hardware is strong enough (lots of hardware horsepower) then it can easily pick up the tap and everything may stay under those mysterious Human Constant values. As long as that equilibrium is balanced nobody cares.

But why am I telling you all this? I want to make the point that the Software Tax is the part developers have the most control over and it is also the most flexible part. I don’t expect humans change their perception much in the next 10 years. If we all do so, then we will most likely get more impatient. Hardware gets faster every year but during a typical 12-18 month production cycle of hardware generations you have to treat the Hardware Horsepower as a constant.

 

Pirates Love Daisies

That leaves Software Tax as the component that will have to bend in order to keep our equilibrium in balance. As you well know there are countless ways of writing web apps (apps that run in browsers). I would argue that on all desktop platforms  the hardware is currently probably strong enough to run almost any JavaScript in browsers. But the picture seems very different on mobile devices. For example try playing Pirates Love Daisies on the iPad. You will probably quit the app while it is still loading (1 s < SW/HW). If you do wait until you can play the game you will notice that the game itself is way too slow and runs at around 6fps (SW/HW = 6fps = 167ms per frame ;  50ms < 167ms). Pirates Love Daisies is as far as I know a project sponsored by Microsoft perhaps to promote their modern versions of Internet Explorer (IE9, IE10, IE++). I don’t think that running on Apple devices was a requirement for this game. But if it were they would have to lower the Software Tax by at least switching their Canvas based architecture to SVG, which is hardware-accelerated.

 

La Quenta, Por Favor

So what does this all have to do with “dynamic” versus “static languages”? Why do I prefer static types for practical reasons? Isn’t “dynamic” versus “static languages” a question of religion?

This is how I would like to tie the different threads together: ActionScript is a dynamic language like Dart and JavaScript and allows you to use no types at all if you wish. From my experience using Object and Array all over the place comes with a hefty Software Tax, because dynamic language expressions are extremely hard to analyze at compile time. As a result untyped code will be less efficient in size and performance than typed code once cross-compiled to JavaScript and optimized with the Closure compiler. Now, on desktop platforms you can probably get away with a “dynamic coding style”. But the hardware on mobile platforms is still not quite powerful enough to process unoptimized and less efficient JavaScript. I am afraid that you simply cannot afford to use dynamic language expressions if your target platform is iOS or Android. You can always sit it out and wait until the hardware catches up if dynamic is so important to you. It is not for me. In these days, the so-called Dark Ages, where my SmallTalk app refuses to launch on my high-tech toaster, I would rather stick with typed code.

 

That said, I would like to end this post. My wife wants to go down to the market here in Oaxaca, Mexico. She is eager to buy a musician-skeleton wearing a sombrero (calavera).