Faster Code

Note

I won’t claim that my suggestions will make the code perfect, merely that they will make the code better (at least in my biased opinion).

Take another look at the code from the previous section. To keep things simple, let’s just consider the Python version:

# Compute the vector product of the two velocities
i = 10
while j < i+1:
    k = i + 3
    s[j] += k*j
    j += 1

I’ll start with this line:

while j < i+1:

What is the value of i+1? It’s 11, since we have i = 10 on the line above. Is the value of i+1 going to change as we go through the loop? No, there’s nothing that changes the value of i in the loop, so i+1 will be unchanged.

But Python doesn’t “know” that. Python is an interpreted computer language: The Python interpreter looks at each line, one-by-one, converts that line into the native computer machine language, and executes it.1

That means that every time the Python interpreter goes through the loop, and interprets the statement while j < i+1:, it’s re-computing the value of i+1. Since i never changes (in the loop), i+1 never changes. Yet Python must go through the additional step of adding 1 to i each time.

Therefore, I claim:

Speed problem 1: The loop performs an unnecessary computation of i+1 for every iteration of the loop.

Now you’ve probably already guessed:

Speed problem 2: The loop performs an unnecessary computation for k = i+3 for every iteration of the loop.

Again, since the value of i+3 never changes, the value of k never changes. Yet Python must spend time re-calculating k.2

Note

Why this fuss over a simple addition? Computers are fast, aren’t they? And it’s just an addition, not calculating the space-time tensor in the vicinity of a black-hole merger.

But:

  • Programs and goals change over time. Right now a loop may be going through 11 entries in a table. Tomorrow it may be going over 10,000 entries.

  • In my experience, paying attention to what’s actually modified in a loop helps one write code that is easier to read and debug.

Let’s revise the Python version with those two points in mind:

# Compute the vector product of the two velocities
i = 10
k = i + 3
m = i + 1
while j < m:
    s[j] += k*j
    j += 1

Well, it’s faster… but there are still problems with it. We’ll look at them in the next section.


1

For anyone familiar with compilers and interpreters, I’m skipping over a lot of details here. However, the details (as important as they are to the overall science of computing) still support my point… I think.

2

If you’re a C++ programmer, your reaction may be that these two points are meaningless for an optimizing compiler. That’s a legitimate reaction, but I maintain it’s no excuse for sloppy code.