2010 in Review

These were the most linked-to posts on my blogs in the last year:

Happy new year, peace on earth, and may all your builds be green!

Making the leap to SSD...

The Intel SSDs were on sale around Thanksgiving, so I picked up one for my Thinkpad.

There is little that was remarkable in getting it set up. I swapped out the old spinning rust device. (The X201, unlike any other laptop I've opened up, has rubber shock absorbers that fit between the drive and the chassis. Not that the thing they're guarding is particularly susceptible to mechanical damage any longer.) Everything just worked.

Boot times and application load times are dramatically improved. Though, the way I work, my laptop is essentially just a device for running Emacs, Chrome, and gnome-terminal, all of which I just open and keep open. All of those apps load fairly quickly, so the speed improvement from the SSD, while nice, is not by any means life-changing. (And, how often do you reboot a computer, anyway? But, for the record, my Thinkpad goes from LUKS password prompt to login screen in 10 seconds, and to a ready-to-use desktop in about 3 more.)

What's really nice about the SSD is that my laptop is now nearly silent, or at least quieter than ambient noise. Perhaps I just have unusually low noise tolerance, but I find the steady-noise of a HDD to be somewhat annoying, and the sound of a HDD spinning up to be even more annoying. Unfortunately, I actually didn't correctly attribute those noises to the HDD until recently. If this sounds like you, it's time to pay a visit to the computer store.

One caveat is that if you use LUKS full disk encryption (and if you're using a laptop, you really ought to; no, I mean, you really ought to), then Ubuntu (10.10) doesn't issue TRIM commands to the device. Which will eventually lead to decreased throughput, but I believe that may just be the price of security. (IANA security expert...) LUKS goes to great lengths by default to foil cryptanalysis, including initializing encrypted partitions with random data to obscure which sectors of the device are actually being filled with interesting data. This would all be for naught if the OS was periodically telling the device exactly which sectors were no longer being used.

Content-aware image resizing by seam carving

This is a classic, or, as much of a classic as a 3-year-old graphics paper can be.

Seam Carving for Content-Aware Image Resizing (Avidan and Shamir, 2007) describes a technique for resizing photographs along one dimension in a way that allows the aspect ratio to be changed while reducing the amount of distortion in perceptually important parts of the image. Watch the video, if you haven't seen this before:

Youtube link

The algorithm translates into identifying the shortest path in a DAG and it can be easily implemented by a dynamic programming algorithm. As Dmitry pointed out to me some years ago, this makes an ideal teaching example for dynamic programming, for a number of reasons. The algorithm is easily visualized because the space of values to be computed maps straightforwardly onto the pixels of the image. Both the naive exponential-time algorithm (testing all 3#rows paths) and the dynamic programming algorithm are fairly easily expressed without too much additional machinery. And, unlike most classroom dynamic programming questions I have encountered, which seemed either banal or contrived, the applications of this one are visually appealing and fairly interesting. For example, as someone pointed out to me, it makes the fallout of breaking up much easier to deal with.

Before... and after (Source: video, above)

Some Android tips

I've been using a Nexus One as my primary phone for about a year now. Here are some tips and suggestions I've accumulated. Most of these tips should also apply to the Nexus S and the G2 (which have stock Android builds), as well as to other Android phones (Froyo+) modulo any vendor customizations.

  • Press and hold the Search button to activate voice search / voice actions. This is indispensable! I use it a least a couple of times every day. It makes the phone feel like future tech, not least because it's dramatically better than anything I regularly deal with in phone systems or on PCs. The phone recognizes special instructions, including things like the following (for anything it doesn't recognize as an action, it asks you to disambiguate or it falls back to a Google search):
    • "Call Phil Sung, mobile"
    • "Navigate to Fry's Electronics"
    • "Map of gas stations"
    • "Note to self, buy more envelopes" (which sends you an email from yourself)
  • Press and hold the Home button to easily get a list of recently used apps.
  • Press and hold the Menu button to toggle the display of the soft keyboard. Not usually needed, but occasionally useful.
  • When using the soft keyboard, you can drag your finger past the top edge of the keyboard for quick access to digits and punctuation.
  • If you add your email address to the user dictionary, you can get it in the list of autocompletions when filling out forms in the web browser.
  • It's important to control the quantity of notifications so that they're at a level that is actually useful. Depending on how important some event is, you can configure the phone to make noise or merely to show you a notification the next time you turn on the phone. As an example, here's how I'm set up:
    • My phone only rings for phone calls, SMS, and IMs.
    • GMail generates a notification in the notification area but no noise (configurable in GMail settings). Even so, I implemented an elaborate system of GMail filters to keep all but the most important emails from getting to my inbox and thus generating notifications.
    • Calendar events generate neither noise nor notifications (configurable in Calendar settings). Instead, I put the Calendar widget on my home screen, and I just look at it whenever I need to. My calendar time is pretty sparsely scheduled, though. YMMV.

Easy wifi autoconfiguration with barcodes

ZXing's Barcode Scanner Android app (the most popular barcode app for Android; it's available on the Market) can now configure a wifi network based on information encoded in a QR code.

So you can say goodbye to having guests/patrons/visitors ask you how to log in to your wifi network every time someone new visits. Instead of having to select the correct network and type in the password (I thought computers were supposed to relieve us of this kind of drudgery), all they have to do is scan a barcode, and boom, they're online.

ZXing's QR Code Generator will help you make such a barcode (select "Wifi network" in the dropdown), after which you can just print it out and leave it in the living room.

If you wish, you can also create such a barcode yourself just by encoding the SSID and password in the barcode payload. Here are a couple of examples that illustrate the encoding method:

WEP: WIFI:S:mynetwork;T:WEP;P:00deadbeef;;

(Example using Google Chart API)

WPA: WIFI:S:mynetwork;T:WPA;P:mypassword;;

(Example using Google Chart API)

Hat tip to Vikram Aggarwal who implemented this concept, originally as a standalone app, WyScan, and then later implemented it in the Barcode Scanner app.

Inline expansion in bash

bash has a lot of shortcuts to save you typing and thinking time— globs, shell aliases, and history expansion, for starters; and a bunch more.

When you use bash shortcuts extensively, though, you often end up with inputs that are rather, er, opaque, e.g.

$ !-3 -r [mnop]* !-3$

You have to be fairly brave to press ENTER without looking over that a few times. There is, though, a way out. Instead of trying to analyze what the hell it is you just wrote, you could just ask the computer to tell you exactly what it's going to do. bash has a number of features that facilitate this by expanding shortcuts for you to inspect before you execute them. I refer to these features collectively as inline expansion.

There are three really useful inline expansion commands you can use at a bash prompt that are essentially complementary to each other:

History expansion

If you add the following to your .inputrc,

$if Bash
  Space: magic-space

then whenever you press space, any history expansions (e.g. !!, !grep, !-2, !-3:1, etc.) are expanded.

You can also, at any time, press M-^ to perform history expansion (no configuration required). I prefer to set up magic space because you can just set it up and forget it about it, and subsequently you have one less thing to think about.

Glob expansion

C-x * expands the previous word into any filenames that match the glob. For example, /* gets expanded into /bin /boot /cdrom /dev ....

Shell expansion

C-M-e expands shell aliases, history, variables, commands, and arithmetic. For example:

  • ls into ls --color=auto (based on any alias directives you have)
  • !grep into grep 2010 mylogfiles (based on your history)
  • $DISPLAY into :0.0
  • `whoami` into phil
  • $((3+5)) into 8

* * * * *

I find these features useful for the same reason I use GNU Parallel the way I do: they really improve the interactivity of my work— in the sense that I get much faster empirical feedback on whether I'm doing a complex task correctly (the computer tells me what it thinks I'm trying to say), rather than me having to reason (unreliably) about what I wrote and recall a bunch of history and read the man page for the umpteenth time because I'm second-guessing myself.

Inline expansion is useful in a different scenario as well, namely, once you expand a glob or a shell alias you're free to (interactively) make changes to it. For example, if you want to delete all the files but one in a directory, start with rm *, press C-x * (which expands the glob into a list of all the files in the current directory), and edit out the name of the file you want to keep. Or if you want to run one of your shell-aliased commands, but without one of the flags, expand it with C-M-e and then edit it.

Further reading: A nice bash tips slide deck by Simon Myers; "Miscellaneous [Readline] Commands" in the bash manual