Saturday, 7 July 2012

Well, I'm floored

How do you floor (or truncate) a floating-point number in JavaScript? (E.g., take a value like 5.7 and get just the 5?). The answer is simple: Use Math.floor. That's the right answer at least 99.99% of the time. It's clear, straightforward, easy to read, easy to maintain. It does what it says on the tin:

console.log(Math.floor(5.7)); // "5"

Sorted.

But you see people doing other things in the name of "performance," which is the purpose of this post: Primarily, to explain what they're doing; and also to see how much actual benefit they're getting from it.

Why performance? On rare occasions, you may have an operation where you need to squeeze every last bit of performance out that you can. The theory here is: Function calls are cheap, but they aren't free, and unless the JavaScript engine you're using does static analysis of your code, when call Math.floor it has to look up the Math identifier (which means walking the scope chain to see if it's been shadowed, before ultimately finding it at the outermost level, the global object), look up its floor property, and then call the function that property points to. So if there's a more direct route, people want to take it when they're looking for every last cycle.

And what they turn to is bitwise operations. JavaScript only has floating-point numbers, of course, but its bitwise operations are defined in terms of 32-bit integers. So when you apply those operations to a number, the first thing that happens is that the number is turned into an integer (whole number) by just chopping off any fractional part (see the internal ToInt32 operation for details). Chopping off the fractional portion is, of course, floors the number — exactly what we want. (Well, with a caveat: The bitwise operators "floor" positive numbers, but they "ceil" negative numbers. "Floor" always goes down, and of course for negative numbers "down" is away from zero rather than toward it; so Math.floor(-12.1) is -13, not -12. When you just chop off the fractional part like the bitwise ops do, you get -12 instead.)

There are lots of operations to choose from that will floor the number without actually changing its value; I'll list them in rough order of how often I've seen people use them:

  • Double bitwise NOT: ~~num
  • Bitwise OR with zero: num | 0
  • Left bitwise shift, but not really shifting: num << 0
  • Right bitwise shift, but not really shifting: num >> 0
...and there are also these, which I've never seen anyone actually use as they're a bit clunkier than the above:
  • Unsigned right bitwise shift, but not really shifting: num >>> 0
  • Bitwise AND with all-bits-on: num & 0xFFFFFFFF
  • Double bitwise XOR with zero: num ^ 0 ^ 0 (or indeed, any other number, but zero is easy to type)

But do they really go faster? As always, it depends on what engine you're using:


Figure 1 Math.floor vs. the bitwise operators
(click image for full-size version)
(interactive version on jsperf)

(Compare only the operations on the same browser; the different browsers were run on different machines, so their speed can't be usefully compared with each other.)

The first take-away from that chart is: Things ain't like they used to be. It used to be that the bitwise operators were a lot faster than Math.floor. But engines have really stepped up their game in terms of scope chain resolution speed and function call overhead/inlining. (To give you an idea: IE7 does the bitwise OR with 0 nearly nine times faster than Math.floor, much more dramatic than any of the results above.)

The second take-away is: On most engines, yes, the bitwise operators are faster than Math.floor, either very slightly faster, or markedly faster. The outlier here is Firefox 3.6, which must have some specific Math.floor optimization as it screams past the bitwise operators. More recent versions of Firefox don't show that behavior.

The third take-away is: All bitwise operators are not equal. Looking at the chart, the best on most engines is the bitwise OR with zero (num | 0; the bright red lines) — unless you're using Safari. The most reliable all-rounder (performs well across engines, even if not in first place most of the time) is, oddly, the signed right-shift (num >> 0; the reddish-pink, second from the bottom of each grouping).

And finally, we can't tell this from that chart per se, but it's worth noting that using the bitwise operators tends to give you the greatest benefit on the slowest engines; e.g., there's not much in it on recent Chrome or Firefox, but there's a much larger difference on the slower IE8, IE9, Opera, and Safari engines (again, Firefox 3.6 seems to be the outlier here).

So if you've been wondering what that n = n|0 was doing in that code you saw, now you know; it's chopping the fractional part off n — either for performance reasons, or because the coder wanted 12.7 to become 12 and -12.1 to become -12 rather than -13. And it looks like, in those very rare situations where it matters, you do actually get a performance benefit where you need it using the more-obscure, but faster bitwise operation to get the job done. My recommendation: Just be sure to comment what you're doing. :-)

Happy Coding!

Monday, 18 June 2012

9pt grey text on a dark grey background

Is it just me? Am I getting old? (Well, yes, but...) Surely 9pt grey text (#646464) on a dark-grey background (#1C1C1C) qualifies as a Bad IdeaTM? How's this for readable:

Form Factormini-PC
CPU SocketIntel® Atom™ D525 (dual-core) (1.8 GHz) Intel® HyperThreading™ technology
ChipsetNM10 Express
GPUIntel® GMA 3150
MemoryUp to 4GB
Harddrive2.5“ drive bay SATA 3.0 Gb/s compatible
Graphics Output1 VGA / 1 HDMI

And even that's better than the original linked above, I haven't managed to find all the styles they applied to mess up the text.

Grumble...

Thursday, 14 June 2012

Too Funny - An IE7 Tax

An Australian online retailer has started charging users of IE7 a tax to use the browser on their website. This was inspired, they say, by the amount of time it took their developers to make the site work correctly with IE7 (which 3% of their users were still using). The tax is currently 6.8% — 0.1% per month since IE7 was released.

Presumably they just aren't supporting IE6 at all — if they did, the tax would be a whopping 13% (at the moment).

Cleaning up old Ubuntu kernels from /boot

My Ubuntu system told me today that it was running quite low on room in /boot. I searched around for what to do about that, and found this answer on Ask Ubuntu. It turns out that when kernel updates are applied, old kernels are left lying around in /boot.
So what to do? It's quite simple:

  1. Ensure you don't have a restart pending (Linux can update just about anything without rebooting...except the kernel). If you do, restart.
  2. Check to see what kernel you're using with uname -a:
    $ uname -a
    Linux forge 3.0.0-21-generic #35-Ubuntu SMP Fri May 25 17:57:41 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
    That's telling me that I'm using kernel 3.0.0-21-generic.
  3. List what kernels you have installed:
    $ sudo dpkg -l linux-image-\* | grep ^ii
    ii  linux-image-3.0.0-16-generic  3.0.0-16.29  Linux kernel image for version 3.0.0 on x86/x86_64
    ii  linux-image-3.0.0-17-generic  3.0.0-17.30  Linux kernel image for version 3.0.0 on x86/x86_64
    ii  linux-image-3.0.0-19-generic  3.0.0-19.33  Linux kernel image for version 3.0.0 on x86/x86_64
    ii  linux-image-3.0.0-20-generic  3.0.0-20.34  Linux kernel image for version 3.0.0 on x86/x86_64
    ii  linux-image-3.0.0-21-generic  3.0.0-21.35  Linux kernel image for version 3.0.0 on x86/x86_64
    ii  linux-image-generic           3.0.0.21.25  Generic Linux kernel image
    
  4. Uninstall the oldest one(s):
    $ sudo apt-get purge linux-image-3.0.0-16-generic
    ...and so on, being sure not to uninstall the one you're using.
Many thanks to Lekensteyn for the answer, and user6722 for the question.

Thursday, 24 May 2012

Finally, the normative ECMAScript Spec - in HTML

Finally a normative ECMAScript specification in HTML. Very worthy private efforts notwithstanding (here, here), having a normative deeply-linkable, HTML edition is huge — and long overdue.

Tuesday, 17 April 2012

John Cleese on Creativity

My good friend Jock Murphy blogged about this video, where John Cleese spends 36 minutes talking about creativity and telling "how many (blank)s does it take to change a light bulb" jokes. I can only echo Jock's sentiments here:

Go watch it. Go watch it now. Utterly brilliant.

Wednesday, 4 April 2012

Announcing Lineage

Note: As of late 2015, I don't use Lineage anymore, there's no need. I use the class features of ES2015 (aka "ES6") instead. If my target is a browser, for now I transpile with Babel (no need when working in NodeJS, the latest Node uses the latest V8 which has solid support for ES2015).

Just a brief post to announce my latest mini-project, Lineage. It's a small, simple toolkit for creating JavaScript constructor functions and their prototypes ("classes," if you will) in a straight-forward and concise way. From the project home page:

  • Lineage's API lets you define prototypes with a very concise syntax, while still encouraging you to create functions with real names (rather than anonymous functions); this helps your tools help you (debuggers show function names in call stacks, for example).
  • Lineage provides a highly efficient mechanism for "supercalls" (calling into the parent prototype's versions of methods from an instance using a derived prototype).
  • Lineage's API encourages and supports use of the module pattern for each constructor and its prototype.
  • Lineage is small, <3k compressed (gzips to <1,500 bytes, a quarter of which is the MIT license) — because it doesn't try to reinvent inheritance, it just simplifies access to the power of JavaScript's prototypical inheritance.

Here's an example of defining a constructor called Thing with a spiffy function on the prototype:

var Thing = Lineage.define(function(p) {
p.spiffy = function() {
console.log("I'm a spiffy thing!");
};
});

...or if like me you prefer your functions to have names:

var Thing = Lineage.define("Thing", function(p) {
p.spiffy = Thing_spiffy;
function Thing_spiffy() {
console.log("I'm a spiffy thing!");
}
});

Now, with such a trivial example, that doesn't offer you much on top of the raw equivalent:

var Thing = (function() {
function Thing() {
}
Thing.prototype.spiffy = Thing_spiffy;
function Thing_spiffy() {
console.log("I'm a spiffy thing!");
}
return Thing;
})();

...and that's the point, Lineage works with JavaScript's natural inheritance, it doesn't try to reinvent things. But when you get into inheritance, and in particular start making supercalls, Lineage reduces the code markedly while ensuring everything is hooked up properly, and does so in a way that's easy to use correctly, without retyping a lot of boilerplate code.

Rather than loading up this post with code examples, I'll point you to the progressive series of examples on the Lineage Comparison with Plain JavaScript page for more.

I'm using Lineage in projects now, and so far I'm really liking the simplicity of it. I hope you will too! If you do play with it, please send comments (positive and negative!), the feedback is very welcome.

Happy coding!