Archive for August, 2006

OK Go on treadmills

I have to admit I’ve seen this video on TV several times now, and it never fails to amuse me. The video always looked grainy, in that Flash video sort of way, so I often wondered if it was pulled from online.

Apparently, it was.

I’m not sure why this video always puts a smile on my face, but it does. Maybe its the creative use of treadmills, or the fact that a couple of them look like they could use it a bit more often.

Yahoo also has a write up on OK Go and their now viral treadmill video, which is how I found the above link.

Xcode scavenger hunt

I’ve always enjoyed a good scavenger hunt for the way it can get rid of unwanted people without hurting their feelings. This is why they’re particularly effective at the end of a party, when you’re busy, or when you need a reason to have random people arbitrarily obey your whims and enjoy it.

Organizer: Here, go look for these random objects I just thought up!

Participant: OK! Where do you think I can find one of these “cow catchers”?

Organizer: Just stand on these tracks and it’ll come right to you.

Participant: Wow, thanks! I love scavenger hunts, they’re so fun!

But I digress.

Surprisingly, there are ways to have a scavenger hunt without committing a felony. I’d like to try one now. See if you can find the following things in Xcode:

  • Your dignity, when the Xcode’s linker locks up the entire machine, except for iTunes, and your business partner calls and you have to explain why The Breakfast Club soundtrack is blaring in the background.
  • Which symbol you haven’t defined, but your linker won’t tell you about, because Xcode turns on ZeroLink (motto: We eliminate the most important job of a linker so you don’t have to!) by default in hopes that you’ll give up on your product idea, and just email it to Apple directly thereby cutting out the middleman.
  • The file you just had opened, but accidently closed, but can’t access from the Open Recent menu because source files aren’t project files, and nobody ever needed to quickly access anything but project files, you big jerk.
  • A button in the Find in Files dialog that says, “No thanks, I don’t want a Find Set, I’d just like to search this folder.” Bonus points if it doesn’t require creating a Find Set to enable it.
  • Any way to make Open Quickly slower or more inconvenient. Requiring three or more keys to invoke it or ensuring it searches the smallest set of files possible do not count, because Apple has already thought of those. (Hint: it should include Find Sets in some way.)
  • A clue of what might should happen when you double click on a function in the debugger’s call stack. (Hint: Look at CodeWarrior.) If you find this, don’t give it to me, email it to the Xcode team. They need it.
  • The state of the program when a call to DebugStr() or Debugger() happens and Xcode quickly, efficiently, and without error doesn’t stop for them.
  • Code demonstrating the technical reasons for why Xcode can’t save the window locations of a project when the files they are stored in are not locked, although the file next to them is. (Hint: the code should invoke the Heisenberg Uncertainty Principle, or involve a lot of illegal narcotics.)
  • A flowchart that explains the optimal way in which to obtain the new developer documentation that Xcode insists on telling me about every five minutes, in an application modal dialog. Bonus points for why its not in the Software Update or why you need an NDA to read about how Quickdraw is deprecated in four different languages.
  • The cure for Xcode’s Alzheimer’s, who cannot remember between runs that I selected “Show Types” in the debugger, despite the fact that I yell at it each time to remind it.
  • Your brain, after attempting to determine what correlation or relationship there is between what you selected for Go To Symbol (command-double click), and what Xcode actually retrieved.

How many were you able to find? Entries can be submitted via Apple’s Blackhole of no Return, which, for some reason, they insist on calling “Bug Reporter.”

C++ inline abuse

I’m not sure what it is about inline that makes people abuse it. Maybe its the assumption that its an easy way to increase performance or that it saves time when writing code. Unfortunately, misusing inline often causes more problems than it solves.

The only legitimate use of inline is to increase performance. If you’re calling a function a lot, and the overhead of the actual function call is a significant portion of the time spent, then inline is appropriate to use. The overhead doesn’t include the actual body of the function, but the prologue and epilogue that set up and tear down the stack. So if you’re trying to increase the performance of a function itself, inlining won’t help you.

For some reason, some people think inlining is a harmless way to get performance increases. That is, just inline whatever you feel like and you’ll obtain a performance boost, with no adverse side effects. If only that were true.

Problem number one with inlining is maintenance. Anytime that you modify an inline function, anyone who even includes that header file has to be recompiled and linked, regardless if they use the inlined function or not. If you’re on a project of any size, that could turn out to be a lot of files. As a result, inlining increases build times, thus lengthening development cycles.

Problem number two is readability. Most engineers realize that well designed classes encapsulate and hide the implementation. In a way, inlining breaks that by showing implementation in the public interface. Hopefully, most well written classes are used (read) more often than they are modified (write). If I’m trying to use your class, I scan the public methods. If you have inlined functions in your public interface, that’s a lot more code that I have to climb over to get the information that I want.

The other part of readability comes in when debugging. I’m not sure why, but when people inline functions they like to put it all on one line, as if the compiler charged per line used. If someone else comes through and tries to debug the inlined function, its impossible. They cannot set a breakpoint where they want, nor can they accurately step through the statements. Personally, this is one of the more aggravating problems of inlining, although its not inherently caused by inlining.

Also, by putting inlines in the header, you separate that part of the implementation from the rest of the implementation. Most people go to the implementation file (.cpp) when they want to figure out how things work. But then they have to start switching between the header and implementation files, if there are inlines.

Problem number three is code size. Don’t forget what inlining actually does. It copies that code into the places where the function would normally be called. In some cases, it doesn’t increase the code size by much. But for large functions or functions that are used all over the place, this can result in a significant increase in the executable size. That means more paging out to disk, and a longer download if you are distributing over the web. That might be fine if you’re getting an actual performance increase.

Of course, this all assumes inlining will get you better performance. Most of the time it won’t. For most accessor functions there is little or no overhead to calling that function. On the PowerPC functions that do not call other functions can operate in the “red zone,” which means they don’t have set up or tear down a stack frame. So there is very little performance increase in that case.

Furthermore, most inlines aren’t called enough times to save any real time. By real time, I mean time the user will actually notice. Remember, inlines only remove the time required to set up and tear down a stack frame. The time to do that usually isn’t that significant unless you’re calling the function thousands of times in a very short interval. If you just call the function fifty times when the user selects a menu item, sorry, no one will notice that its inlined. You are not giving the user any benefits. But you are inconveniencing yourself and other developers.

There does seem to be one popular reason to use inlines that I do not understand. That is, to save the developer time when writing code. Yep, apparently some people can’t be bothered to switch to the implementation file when writing functions, so they will simply inline the function where they declare it. They are not even attempting to use inlines for the purpose they were invented, but do managed to foist all the disadvantages of inlining on the function. It is a lose-lose situation.

Worst of all are virtual inlines. That is, functions that are declared both virtual and inline. I’m not sure how the authors of these functions actually expect these to work. Inline is a suggestion to the compiler, not a command: just because you ask, does not mean you will receive. A compiler cannot inline a virtual function, unless it knows its type is static. e.g.


class Foo {
inline virtual void bar(void) {
std::cout << "hello world" << std::endl;
}
};

...

Foo foo;
foo.bar();

In this case, bar could actually be inlined because the compiler knows what type foo will be at runtime. However, in most cases, virtual functions are used like this:


class Foo {
inline virtual void bar(void) {
std::cout << "hello world" << std::endl;
}
};

void CallBar(Foo* foo) {
foo->bar();
}

In this case, the more common case, the compiler can’t inline. foo could be a Foo or any other derived class that overrides bar(). Once again, all the inconveniences of inline, without any of the advantages.

Don’t get me wrong, I’m not trying to say never use inlines. There is a legitimate use for them. You use them when a function is called enough times that the overhead becomes significant.

There are certain guidelines I follow when using inlines.

First, I only use inlines for performance reasons, and only when a performance tool, such as Shark, indicates a problem. Some engineers just start inlining functions in a module when they think that module is slow. That makes no sense.

Think of it this way: when you get a crashing bug, what do you do? Do you start randomly start changing code in the module where you think the crash is happening? Or do you use a debugger to figure out where the crash happens, and only change code after you’ve determined the cause? I think just about everyone uses a debugger to determine the cause first. In the same way, performance problems are just another bug. But instead of using a regular debugger to find the problem, you use a performance debugger, such as Shark, to find the problem. Then you change the code.

Second, when I do use inlines, I don’t put them inside the class declaration, but at the bottom of the header file. Like so:

class Foo {
inline void bar(void);
};

inline void Foo::bar(void) {
std::cout << "hello world" << std::endl;
}

That way, the implementation is inlined, but out of the way so the public interface is easier to read.

Third, I try to determine if I can change my algorithm to simply not call the function as often. It is frequently a more drastic change to make, but it also frequently is a more drastic performance increase than a simple inline.

In the end, inlining can get you performance increases. Just not as often as most people think, and not without some complications.