iPhone + Microscope = Awesome

January 3rd, 2012

I was trying to repair my TV, and I wasn’t happy with the crummy iPhone camera resolution of this chip:

So I took the part to work, put it under the microscope, lined up the iPhone camera with the eye piece, and voila!

I put my left index finger in the frame for size reference.

Note: in the second photo, the chip has been removed. :)

Book Review: Treading on Python

December 28th, 2011

Treading on Python by Matt Harrison provides a basic introduction to the Python programming language for programming novices.

Background of the reviewer

I have been writing code professionally for 10 years. I’ve spent most of my time in C++, but I’ve written a handful of small Python scripts (less than 100 lines) and a couple medium-sized Python applications (hundreds of lines with multi-threading).

In Treading on Python, I was looking to shore up my Python foundation before jumping into my first big Python project.

I was not disappointed.

Who is this book for?

If you are interested in learning how to write computer programs as a beginner, this book is probably a pretty good place to start. The book starts by persuading you to choose Python as your first programming language for two main reasons:

  1. Python is used widely in industry
  2. Python is easy to learn

This book is written primarily for brand new programmers. It provides practical advice for getting started at the very early stages of programming:

  • How to edit Python code
  • How to run Python programs
  • How to use the Python interactive shell
  • What a variable is (complete with cattle analogy)
  • How to use strings, integers, and lists

However, even if you have, like me, written some small to medium sized Python programs, you will still probably benefit from the following useful information:

  • Python’s handy dir and help functions
  • The enumerate() function
  • The dictinoary setdefault() method
  • Python’s concept of None and object id
  • List slicing
  • import and from...import semantics
  • And a surprisingly good list of pitfalls to avoid

Early in the book, Matt spends a lot of time explaining basic programming concepts (like variables). He does this by providing real world analogies (like cattle) that will probably seem superfluous to the experienced programmer, but that may be beneficial to the programming novice. I was tempted to skip the first few chapters but I’m glad I read them competely. The book is peppered with little gems that reveal what writing Python code is all about, and even the most basic topics still provide these insights.

Who is this book not for?

If you are looking for a book that delves deep into Python, this is not the book for you. Notably absent concepts from this book include:

I don’t offer this list as a criticism of the book. The book’s stated purpose is clearly not to provide a comprehensive Python treatise for the experienced programmer. But if you are considering this book as a way to delve into any of these concepts, this is not the book for you.

Opinion of the book

Matt clearly knows his Python. He has peppered the book with helpful tips that compelled me to whip out my Python interpreter to experiment. Many of the tips were very handy, even for a semi-experienced Python programmer such as myself.

Matt is pleasingly frank in his recommendations to avoid certain approaches, and after reading the book, I feel like I have a better eye for assessing how “Pythonic” something is. In fact, now that I have finished the book, I can look back on Python code I wrote before reading the book, and critique the heck out of it. Prior to reading this book, my Python code looked a lot like my C++ code, which is just a shame. This book can help inoculate you against such behavior.

The book reads smoothly and quickly. Matt is very careful to keep his explanations succinct and clear, such that you don’t feel like you’re reading a college text book or a reference manual. Even still, the book does contain a high information density.

On my iPad, with the default font size, the book is 243 pages in landscape mode and 147 pages in portrait mode.

I finished the book in fewer than a dozen 15-30 minute sittings.

Conclusion

If you can already crank out Python list comprehensions and lambda expressions, this is probably not the book for you. If you are an experienced programmer and want to learn Python, this is a fast way to start. If you are a total programming novice, this may be a good way to begin, but I’m not a great judge for this audience.

Fun Python Solution to Euler Problem 79

December 27th, 2011

Nothing says Merry Christmas like Project Euler.

Here’s a nifty solution to Problem 79 that uses Python and Graphviz.

The problem is to identify a user’s password given a bunch of successful logins (taken from some kind of nefarious keylogger–those crafty devils). The çatch is that each login is actually a subset of the actual password. Of course, they give you a sample of 50 successful logins.

So I decided to whip up some Python code to ingest each login and store a list of digit precedence. Then, the code prints out a Dot file which we turn into an image using the “dot” command. I ran this on Mac OS X, but it should work just fine on any Linux box (hint: install the “graphviz” package).

Here’s the Python code:

problem79.py:

digit_precendence = dict()

for line in [line.strip() for line in open("./keylog.txt")]:
    for index, char in enumerate(line):
        digits = digit_precendence.setdefault(int(char), set())
        if index < len(line)-1:
            digits.add(int(line[index+1]))

print "digraph problem79 {"
for (digit, subsequent_digits) in digit_precendence.iteritems():
    for subsequent_digit in subsequent_digits:
        print "   %d -> %d;" % (digit, subsequent_digit)
print "}"

Save that as problem79.py, download keylog.txt into the same folder, and run the program like this:

python problem79.py | dot -Tpng > problem79.png

Then view problem79.png, and voila! Graphviz just put the answer right in front of your nose: 73162890.

Cocoa Noob Pitfalls

September 12th, 2011

I just finished writing my first iPhone app. I have a background in Java, C++, Python, and a smattering of other programming languages on Linux and Windows in both embedded and desktop environments, so that hopefully explains my brain damaged context.

Here are the pit falls I stumbled upon while climbing up the Cocoa learning curve:

Retain/Release Memory Leaks

It wasn’t immediately obvious to me that adding an NSObject pointer to an NSMutableArray (and other containers) would actually increment the NSObject’s retain count. Not knowing this right away, I got into the (bad) habit of double-retaining objects. It took some investigation to find out what was happening, and thanks to Apple’s ingenius profiler and analyzer, I was able to identify the problem. After learning this, I came to find out that, by convention, lots of containers do this, but it’s not too apparent from the documentation.

No Container Static Type Checking?

Apple provides several container classes, including NSArray, NSDictionary, and several others. Much like old versions of Java (like the Java 1.3 stone age), you are free to add instances of any NSObject* child class. As a result, it’s possible to end up with objects of types you did not expect, and the compiler cannot prevent you or even warn you about this.

Sub-Class Insanity

It seems you have to sub-class to do very basic things, like adding items to a UIPickerView. I would have expected a trivial method call to do something like this.

Verbose Names

Stuff like appending one string to anoher is usually pretty trivial and terse in most languages. For example, in C++, you might see this:

myString += "suffix";

But in Cocoa, it looks like this:

myString = [NSString stringByAppendingString:@"suffix"];

That is a seriously verbose method name. If you count, it uses the word “String” 3 times, and that’s not even counting my variable name.

No Static Function Checking

Because Objective-C’s message-passing system is evaluated at runtime, the compiler won’t complain (much) if you try to send a message to an object that does not respond to that message (i.e., like calling a member function in C++ that does not exist). The compiler does warn you, but it will compile, run, and fail with a run-time exception. Some people consider this an advantage of Objective-C, so I can’t hold it against Apple (Smalltalk fans, I’m looking at you).

Bogus Compiler Warnings

If I define a couple messages like this in my class, without putting them in the .h file:

-(void) foo
{
    [self bar];  // compiler warning here
}

-(void) bar
{
}

The compiler will issue a warning, even though this is perfectly safe and will run without exceptions. The compiler is apparently very eager to warn you about this perfectly safe usage, and yet still allows you to send messages that definitely won’t be responded to at run time.

Weird Autorelease Pool Crashes

The first time I misused the autorelease message, I discovered that my application would crash in the event loop processing context. The stack gave no indication where I had gone wrong, because it contained none of my own code. The autorelease pool object itself would crash because it was calling release on an object that had already been freed. The runtime exception was so counter-intuitive that I ended up reverting my code (using git) back to a prior state. I eventually isolated the cause of the problem to my misuse of autorelease, which prompted me to do a more thorough exploration of the feature. Now I recognize those kinds of crashes for what they are, but the first time I encountered it, I was confused for a while before I figured it out.

Managing Multiple Sub-Views

If you have multiple UIPickerView sub-views within your view, managing their contents can be difficult. This is because you have to write a class to implement the UIPickerViewDataSource protocol, which is usually easiest to do right inside your view controller. However, when you add a second or third UIPickerView sub-view to your view, it gets difficult to manage. The UIPickerViewDataSource protocol sends you a pointer to the UIPickerView so you can keep track of which one is which, but it just feels cumbersome. I ended up using this guy’s code to make it easier.

Permissive Compiler Stuff

The Objective-C compiler will allow you to do this:

NSMutableDictionary *myDictionary =
    [[NSDictionary alloc] init];

I would expect it to work the other way around, but not this way. This leads to runtime exceptions when you try to add an element to “myDictionary”, which can be surprising until you realize you have an instance of an immutable NSDictionary. The runtime exception is pretty vague too: All you get is “invalid selector”.

Disappearing Outlets

If you connect an outlet or action in Interface Builder and then later delete the outlet or action object in your Objective-C code, you will get a very cryptic error when you try to instantiate the view:

'NSUnknownException", reason: "[<uiview 0%48a3e0>
setValue:forUndefinedKey:]: this class is not
key value coding-complaint

What it should say is “This xib file is trying to reference item ‘foo’ which does not exist”

Working with UINavigationController

UINavigationController can only have one delegate, even though all it does is notify the delegate when the current view changes. If you want to notify more than one view controller that navigation has moved, then you have to do some juggling to save and restore the UINavigationController’s delegate. It should be easier to notify interested parties when navigation changes.

Good Stuff

Cocoa has a lot of good stuff about it too. Here are some of the highlights from my experience:

Consistent Time Units

Times are always expressed in seconds (and fractions of seconds) instead of having to guess whether it’s seconds, milliseconds, or something else. This is extremely gratifying having come from a world where you pretty much always have to guess (although Google Go’s concept of typing is still far superior).

Analys and Profiling Tools

The X-Code 4 analysis and profiling tools are excellent. I mostly learned how retain/release worked by following the memory leaks that the code analyzer told me about. It even draws little arrows on your code to show you the code path you screwed up. Also, the memory leak finder is fantastic. It shows you when your application leaks, and where each leaked object was originally allocated. This made it trivial to track down and fix my memory leaks.

Easy Animation

Animation is as easy as giving a view a destination size and position, and telling it to go. Animation is integrated into the very core of Cocoa, and it is both easy to use and beautiful on screen.

Conclusion

So there you have it. Cocoa has some pitfalls and some good stuff. That’s all I have to say about it.

Linode: 7 years of awesome

April 18th, 2011

It just ocurred to me that I’ve been using Linode as my hosting provider for 7 years this week. I’ve been so happy with their service that I thought I’d offer a review.

The top 4 reasons you should consider Linode for your hosting needs (I’m sure there are 6 more reasons, but I’m time limited today):

Reason 1. Automatic Upgrades

Every year or so, I wake up to an email from Linode telling me I can have more disk space or RAM on my server. Adding it is super easy: just login to their web site and click a few buttons. Today I’ve got 490 MB of RAM and 16 GB of disk, and I’m still only using their least expnsive option.

Reason 2. Huge Internet Speeds

Linode servers have great Internet connection speeds. I regularly get over 50 Mbits/second.

Reason 3. Customer Service

The Linode support team is very sharp. They know what they’re talking about, and they are very helpful. This is more than can be said for many other support organizations. I’ve only needed to open a support ticket a cople times, and on both occasions, the Linode support staff responded within an hour and gave me all the information I needed, not only to solve my problem but to prevent my problem from happening again in the future

Reason 4. Cost

At $20/month, Linode is very affordable for what you get: Full root access, nearly any Linux distribution you want, lots of RAM and disk, and good CPU speed (my Linode has 4 CPUs).

After 7 years, I very highly recommend Linode as a Virtual Private Server hosting service.

LDS General Conference Podcast Updated

April 3rd, 2011

There were some fantastic messages this conference (April 2011). I plan on re-listening to all of them.

Get the podcast: General Conference Podcast page.

When faster is actually slower

February 12th, 2011

This is a follow-up to my post on code optimization.

Today I did some experimenting with hashes and binary-search-trees, specifically playing with QHash and QMap in C++.

According to the Qt containers algorithmic complexity documentation, QHash provides “significantly faster lookups” than QMap. Your intuition may confirm this, because you’ve heard that QHash uses a constant-time algorithm for lookups, while QMap uses a logarithmic algorithm. However, when it comes to performance questions, intuition is not the best guide.

When considering the QMap vs. QHash speed question, we have to consider everything these classes do when you are looking up an entry. Otherwise, you may be led to assume that QHash lookups are faster than QMap lookups in all cases.

How does QMap work?

Like an associative array or dictionary, the QMap class allows you to store values identified by keys. You can insert key/value pairs into the QMap and retrieve values by key. You can use any type as the value, but the key type must implement the < operator. This is because QMap looks up keys using a binary search through a sorted list.

How does QHash work?

QHash also provides the ability to insert and lookup values like QMap, but its implementation is quite different. Keys used in a QHash must implement the == operator and there must exist a global qHash(key) function for the key type. The QHash class hashes each key on lookup to find the position for each key’s value. This is a constant time operation (amortized). This means that the time it takes to lookup a key does not depend on the number of keys already stored in the QHash.

When is QHash slower than QMap?

Consider the following example:

QHash<QString, int> myHash;
QMap<QString,  int> myMap;

To insert the key “my favorite number” with the value 42 into myHash, the QHash has to first generate a hash code for “my favorite number”. To do so, it uses the qHash() function, which reads every character of the string “my favorite number”. This generates an index that is used to locate the position for this entry. Notice that qHash() must read every character of the string. The QMap, on the other hand, uses the < operator to compare the string “my favorite number” with all other keys in the QMap.

Now let’s suppose we filled myHash and myMap with 1 million short string keys (like a few characters each), and then did a few lookups.

I measured this case using QTime, and found that QHash lookups are about 3 times faster than QMap lookups in this scenario.

This is what I would expect after reading the documentation, but what if the key strings are bigger, like 200 characters each, and all quite distinct from each other?

I measured this case and found that QHash lookups are about 3 times slower than QMap lookups.

How can this be? The documentation says that QHash lookups are supposed to be faster.

The reason is this: Because QMap uses the < operator, it does not need to inspect every character of each key string. Instead, it compares the key string to other key strings, one character at a time, and stops if it discovers a difference before reaching the end of the string. This results in much less computation when locating a key’s value. So much less computation in fact, that even though QMap’s lookup algorithm is logarithmic, it is actually faster than QHash’s constant-time lookup algorithm on the same dataset.

I should offer the disclaimer that QHash will likely be faster than QMap for larger quantities of entries with that key size, but I was unable to test larger quantities due to the limited amount of RAM in my laptop.

Conclusion

When optimizing for speed, always consider all factors. Just because an algorithm is constant time does not mean that it is always faster than a non-constant time algorithm. And always remember to measure execution speed before assuming that one approach is faster than another.

How to optimize your code

February 6th, 2011

Disclaimer 1: This post was influenced heavily by my good friend, co-worker, and Haskell hacker Evan.

Disclaimer 2: Unless otherwise noted, I am completely making up terms in this article. I pulled them right out of the ether. Don’t expect to find industry conventions that agree with me.

Bob is a fictitious developer on my software team, who suggested that we could speed up some of our Qt/C++ code. The code under scrutiny is this:

for(int i=0; i<someList.count(); i++)
{
    SomeClass *ptr = someList[i];
    // Do something with "ptr" here
}

Bob suggested that we do this instead:

SomeClass *ptr;
for(int i=0; i<someList.count(); i++)
{
    ptr = someList[i];
    // Do something with "ptr" here
}

Notice how we moved the ptr declaration outside the loop? That way, Bob surmised, the program doesn’t allocate memory for ptr once per iteration of the loop. That should speed things up, right? Right?

This is an example of what I call Intuition-based Optimization, or IBO for short. IBO is a method of speeding up your code where the only tool you use is the raw power of your brain. It’s where you apply human intuition to optimize your code, and no other tools, like profilers or measurements of any kind.

When you use IBO to speed up your code (or attempt to speed up your code), you should always remember the first and only rule of IBO:

The First and Only Rule of IBO: You are wrong.

There’s only one rule. You are wrong. If your computer program has a performance problem, and all you’ve done is think about what might be causing it and try to fix it, even if you use the almighty power of your human brain, which in its own right is a pretty advanced computer, you are wrong. You just are. Even if you aren’t wrong (hint: you are wrong), and the only tool you use for optimizing your code is IBO, then you don’t have a way to measure the effect of your code changes on your program’s actual speed.

All but the most obvious performance problems require tools to measure the effect of your code changes, and the most heinous problems require tools to identify where the bottle-necks are even happening.

I’ve lost track of the number of times I’ve used IBO to try to speed up some code, and failed. For example, it should be faster to use a hash-based lookup, like QHash, instead of a BST-based lookup, like QMap, in theory. In practice, though, there are other considerations. How many elements are in your data structure? How fast are the elements’ hash-code functions vs. their comparison operators? Just because an algorithm is O(1) doesn’t mean it’s faster than an O(n) algorithm. There are just too many other variables besides order of complexity (not to mention, big “O” notation really only applies to theoretically very large datasets anyway).

So, if Intuition-based Optimization is so crappy at actually making code faster, then what is the right way?

Evidence-based Optimization

Or EBO, for short. This is where you use actual evidence to diagnose performance problems and measure the speed impact of your code changes. There are several techniques for doing this. Let’s look at a few.

Technique 1: The time command

In the simplest of situations, all you want to know is how long it takes your (command line) program to run. If you’re using a Unix-ish operating system like Linux or Mac OS X, you can use the time command to do this. Here’s an example:

$ time some-program

real    0m2.235s
user    0m0.155s
sys     0m0.075s

In a nutshell, the time command will tell you how long your program took to run. Look at the “real” time to get this info. The other two times listed tell you a little about where your program spent its time, and you can read a lot of cryptic details about these numbers from the time man page. For most simple applications, the “real” time is adequate.

Technique 2: Measuring time in your program

A more common case is that a subset of your application is running slowly, but you don’t know exactly where. Maybe you have an educated guess where the code is getting bogged down, but you want to use actual evidence to identify the code that is causing the problem (congratulations on wanting to use evidence instead of intuition by the way).

If you’re using Qt and C++ (which by the way is the only non-insane way to write C++ code), you can use the QTime class to do this. If you are using version 4.7 or newer, you can use the QElapsedTimer class for a little bit more precision, but I have not needed that much more precision.

Here’s how you use QTime:

QTime time;
time.start()

// Code to measure goes here

qDebug() << "Took:" << time.elapsed() << "ms";

It’s fairly simple. There are caveats to be aware of, though. If you are measuring code that executes in less than a few milliseconds, QTime will not give meaningful results. There are a few ways to work around this problem. You can simply increase the number of iterations, using a naive approach like this:

QTime time;
time.start()

for(int i=0; i<10000; i++)
{
    // Code to measure goes here
}

qDebug() << "Took:" << ((float)time.elapsed() / 10000) <<
    "ms per iteration";

You can also get more clever about where to put your calls to QTime::start(). You can use a QTime instance as a member variable and start it whenever it makes sense to begin measuring (perhaps as the result of a user action, like a button click). This can be handy when there are multiple threads involved to measure the sum total execution time.

Let’s use this technique to measure Fictitious Bob’s opening example from above.

Which of these two approaches is faster?

Exhibit A:

for(int i=0; i<someList.count(); i++)
{
    SomeClass *ptr = someList[i];
    // Do something with "ptr" here
]

Exhibit B:

SomeClass *ptr;
for(int i=0; i<someList.count(); i++)
{
    ptr = someList[i];
    // Do something with "ptr" here
]

Intuition tells me that Exhibit B might be faster, because there is less code inside the loop, but I am cautious because I know that when it comes to performance profiling, intuition is wrong (see rule #1 of IBO above). Let’s see what the evidence tells me. Here’s how you measure that using QTime:

QTime time;
time.start();
for(int i=0; i<someList.count(); i++)
{
    SomeClass *ptr = someList[i];
    // Do something with "ptr" here
}
qDebug() << "Exhibit A took" << time.elapsed() << "ms";

time.start();
SomeClass *ptr;
for(int i=0; i<someList.count(); i++)
{
    ptr = someList[i];
    // Do something with "ptr" here
}
qDebug() << "Exhibit B took" << time.elapsed() << "ms";

The results: In this example, I filled someList with a few million pointers and replaced “Do something” with actual code that just incremented an integer by a random number. I ran the code a few times in a row and the answer is:

They’re the same speed

Those of you who are assembly heads would have guessed this already, and the rest of us will probably come to a rational explanation after seeing the results. Evidence-based Optimization has that effect on you: You’ll take a wild guess about the cause of the slowness, and then after you gather some evidence, you refine (or completely discard!) that guess to match the measurements.

Technique 3: Unit Tests

There are times when you create some code that is particularly sensitive to performance changes. Perhaps it’s a piece of code that gets used in a lot of time-sensitive areas of your application, and you want it to be fast, and you want to make sure it stays fast for the life of the project. This is where unit testing is your friend. In the case of Qt, the Trolls have provided us with QBENCHMARK.

QBENCHMARK allows you to write a unit test that reliably measures the execution speed of a code snippet by running it multiple times as needed. It produces nice output that you can capture for posterity. Months later, you can double check that your code is still running as fast as you originally measured by re-running the unit test. I’ve used this technique on a few rare occasions and have been happy to have it.

Technique 4: Web Techniques

Sometimes an application’s slowness seems like it’s out of the developer’s hands to influence. Take for instance a web application where there are many pieces of software interacting. You may have a database, a web server, a browser, and other stuff, all vying for CPU time. In these cases, it makes sense to use tools that are able to observe the application state from an outside source, like Yahoo’s YSlow Firebug add-on.

In this case, YSlow will tell you which parts of your web display are taking the longest to appear on the user’s web browser, which sometimes can tell you a great deal about where your code needs to be optimized.

Technique 5: Profilers

Profilers are a special animal and require careful usage to produce useful results. Almost all of my profiler experience comes from Valgrind on Linux. Running your application under Valgrind produces a log file that lists every function call and how long was spent in each. This can be both useful and overwhelming in sheer quantity of information.

Of course, Valgrind is a very complicated tool, but here are some simple usage examples to get you started.

To profile your application fully, use the callgrind tool like so:

valgrind --tool=callgrind /path/to/your/application

That produces a file (sometimes multiple files) called something like callgrind.out. Don’t try to read that file with an editor. Instead, use an application called KCacheGrind, like so:

kcachegrind callgrind.out

You’ll see something like this:
KCacheGrind Screenshot

There’s no easy path at this point. You’ll have to look at the flood of results and carefully try to learn where your application is spending its time. Notice that KCacheGrind will show you how much time is spent in each function and how much time is spent in “callee” functions, which lets you determine where the heavy lifting is actually happening.

I often like to use the callee graph on the right-hand side to see, by geometry, which functions are the most used. This often tells you which standard library or Qt core classes are being used the most, which can provide a hint as to which of your own code is the culprit

Technique 6: Stochastic Profiling

Disclaimer: I did not invent this term. I heard it first from my brilliant co-worker, Shane, who I believe borrowed it from another discipline.

Sometimes an application will go into a CPU hogging run-away state and it’s impossible to tell where in the code this is happening. If it lasts for more than a moment, you can use a technique called stochastic profiling to sample the program’s state to get a snapshot of the current function call tree.

There are several techniques for doing this.

On Mac OS X, you can use the Activity Monitor’s “Sample Process” button, and see a nice call graph, shown below for the Mail application:

On Linux, you can achieve the same thing using gdb to attach to a process by pid (make sure you have the right permissions), and run the bt command to see where it’s currently executing.

If you do this a few times, you can start to get a feel for where the program is spending its time.

Conclusion

There you have it. Remember that when it comes to optimizing your code for speed, don’t believe your intuition, and learn to use tools to measure your code. Remember to measure, modify, and re-measure.

Happy optimizing!

Five Years of Blogging

October 1st, 2010

This month, my blog matured to the age of 5 years. That’s like 37 in dog years, and 800 in Internet years.

Mom, I hope you’re proud. This is all I’ve got to show for myself.

How to give a killer demo

July 4th, 2010

You’ve been there. You’re sitting in a demo where the lead engineer is presenting a new product to the customer. With laser pointer blazing, he shows off the 300 features of the new Blarney Gadget. He’s going a million miles an hour, switching between PowerPoint and the product on the screen as fast as the keyboard will allow. 50 slides later, he finally finishes, crossing the demo finish line like an Olympic sprinter. He sits down, glad the demo is over, and takes a deep breath. At this point, the audience’s heads turn slowly, like spectators at Wimbledon, to look at the customer, hoping for approval. The customer sits quietly for a moment, leans forward, and asks, “Does this have a new Blarney Gadget?”

This was not a killer demo. I’ve sat through a lot of these, and I’m sure you have too. Fortunately, you can do a few simple things to make sure your demo goes better than this. I have most experience with intimate demos involving an audience of fewer than 30 people. These suggestions work best with that kind of audience.

1. Explain the Setup

Any product worth its salt is complicated, at least under the hood. You’ve just spent a lot of time building a new product with a team of engineers. If it were simple, you wouldn’t need to do a demo to show it off. So you’ve got to explain the background. Here’s a checklist of things that you ought to explain before diving into the demo:

  • Physical configuration
    • Are there cables involved?
    • Explain how everything’s connected
    • Explain the computers involved and where they are
    • Explain all the software involved, with diagrams if it helps
  • List improvements since last time, if applicable
    • “Do you remember how the product used to do X?, and that sucked?”
    • “In the past when I clicked this button, it took 30 seconds to process. Now it’s done in 3 seconds”.
    • “Users told us that this used to be confusing. We’ve tried to make the feature more approachable and user friendly.”

2. Tell the Future

Don’t expect your audience to know whether the demo worked or not. Tell them what’s going to happen when you click that magical button, before you click it, so they can participate in the demo success when it works. Get them to feel the excitement of anticipation, and when it works, they ought to instantly think, “Yes, it worked!”, just like you do. To make this emotional connection, you have to tell the future. Here’s an example of telling the future:

“When I click this button, you will see that light blink (point at it), an on-screen spinner will begin to turn, and about 10 seconds after that, a message will appear with the number forty-two. Any questions on what’s going to happen?”

Take time to listen for questions. Make sure the audience is completely clear on what’s about to happen before you click that button. Don’t rush this.

Then, click the button.

After the process finishes, don’t jump in and say, “See? It worked.” Instead, let the audience come to that conclusion themslves. You gave them enough information to evaluate whether it worked, and if you “told the future” correctly, they will see for themselves. This way, they will believe more seriously that your product works (they verified the results themselves, after all).

3. Face Checks

Take time during your demo to make eye contact with each member of the audience, if possible. If you have more than about 20 people in your audience, you’ll have to limit this exercise. Check for the following expressions in the audience:

  • Confusion: A furrowed brow, looking downward, or a pained grimace
  • Boredom: Eyes glazed over, looking at nothing in particular, or head bobbing
  • Excitement: Eyebrows raised, lots of motion, smiling, or the “ah hah” look

If you catch someone bored or confused, it’s time to engage them. Start asking questions. If you can’t think of a question to ask, try this one:

Any questions?

Followed by a 10-second pause. 10 seconds is a long time in a demo. Count it down in your head, “10 Mississippi, 9 Mississippi, 8 Mississippi, …”

Another list of engaging questions:

  • Does this seem like a good approach to you?
  • Do you think your organization will be able to make use of this?
  • In your opinion, are we on the right track?
  • Are there any concerns with what I’ve presented so far?
  • Do you feel like there’s something we could have improved?

By the way, don’t be afraid to take the conversation in a new direction based on the responses to these questions.

You should do a round of face checks after making important points in your demo. Take a look at each face and spend about 1 second looking for the expressions listed above. Just looking at their faces can cause them to better engage in the demo. The audience needs to feel like they are participating in an interactive experience, and not just “along for the ride” like some kind of academic lecture.

4. Slow the Tempo

Presenters almost always go too fast, especially during demos. I think there are two reasons for this:

  1. They are nervous
  2. The technology is more familiar to the presenter than the audience

As a presenter, you should go slower than you think. You almost can’t go too slow. Here are a few tips:

  • Allow silent moments
    • Just look at the screen and look at the audience.
    • This will let the audience absorb.
    • Don’t fear the silence. Embrace it.
  • Ask what the audience thinks
    • If you get no answer, you are going too fast
  • Draw on a whiteboard
    • This will naturally slow things down
  • For long demos, plan regular breaks

5. Easy on the Superlatives

Avoid words like “fantastic” and “spectacular.” Let the demo speak for itself, and let the audience come to their own “fantastic” conclusions. Instead use phrases like “isn’t that neat?” and “we thought you’d like this.” If the demo is pitched properly, the audience will see how “fantastic” it is without you cramming it down their throat. If you start tossing around superlatives, and the audience doesn’t agree, it will solidify a strong opposition to your product in their mind, and they might think of you as a slimy marketing weasel.

This is one place where Steve Jobs excels. He uses phrases like, “we think you’ll like this,” and “this is really neat,” and “wasn’t that cool?” It’s startling when people get up after Steve and start tossing words around like “phenomenal” and “amazing”. When I hear words like that, I think, “hey, you just show me the product, and I’ll decide whether it’s phenomenal.”

You can use accurate superlatives like “totally new” and “unprecedented”, but be careful to stick to accurate words and don’t venture into the realm of hyperbole.

6. Repeatedly Repeat Yourself

It’s okay to repeat yourself. Don’t worry about insulting the audience’s intelligence. Most people go too fast and shower the audience with so much new information that they get hopelessly lost. Err on the side of too much repetition rather than too little. If your face checks reveal that the audience is bored, you might be repeating yourself too much, but this is unlikely.

7. Trade Vocal Cords

Don’t talk too much. It’s human nature to support ideas when you feel like you invented them. You can use this principle when giving a demo by letting the audience talk through ideas. By letting them talk, you are letting them take ownership of the product, which is a good thing if you want them to be your supporter.

Be a good listener, but be careful not to lose control of the demo.

Pay attention to industry terminology they use, and try to use the same terminology in your presentation.

I think a good ratio is about 1/3 to 2/3. You should talk about 1/3 of the time, and let them talk about 2/3 of the time. This guarantees that they are engaged, and it really helps them solidify all the concepts in their mind. As an added bonus, you just might gain an insight into how they operate, which can help you make your software better for them.

8. Spend Your Time Wisely

A good demo has lots of audience discussion. Getting the ratio right is key. Here’s roughly how I divide my time during demos:

  • 1/4: Setup and background
  • 1/4: The actual demo
  • 1/2: Discussion and Q&A

Notice that it usually takes about as much time to explain the background as it does to give the actual demo. Sometimes, the background actually takes longer, and that’s perfectly fine.

Also notice that about half the time should be spent discussing and answering questions.

Happy Demoing

These tips have helped me demo successfully, and I hope they help you. If you have anything to add, please let me know. I’d love to work new suggestions into this article.