Solution

I l @ ve RuBoard

graphics/bulb.gif

1. What does inline do?

Making a function inline directs the compiler that it may choose to place a copy of the function's code directly into each place the code is used. In the cases where the compiler does so, it avoids generating a function call.

2. Does making a function inline increase efficiency?

Not necessarily .

First off, if you tried to answer this question without first asking what you want to optimize, you fell into a classic trap. The first question has to be: "What do you mean by efficiency?" Does the above question mean program size ? Memory footprint? Execution time? Development speed? Build time? Or something else?

Second, contrary to popular opinion, inlining can improve or worsen any of those aspects of efficiency:

  1. Program size. Many programmers assume that inlining increases program size, because instead of having one copy of a function's code, the compiler creates a copy in every place that function is used. This is often true, but not always. If the function size is smaller than the code the compiler has to generate to perform the function call, inlining will reduce program size.

  2. Memory footprint. Inlining usually has little or no effect on a program's memory usage, apart from the basic program size (above).

  3. Execution time. Many programmers assume that inlining a function will improve execution time because it avoids the function call overhead, and because "seeing through the veil" of the function call gives the compiler's optimizer more opportunities to work its craft. This can be true, but often isn't. If the function is not called extremely frequently, there will usually be no visible improvement in overall program execution time. In fact, just the opposite can happen. If inlining increases a calling function's size, it will reduce that caller's locality of reference, which means that overall program speed can actually worsen if the caller's inner loop no longer fits in the processor's cache.

    To put this point in perspective, don't forget that most programs are not CPU-bound. Probably the most common bottleneck is being I/O-bound, which can include anything from network bandwidth or latency to file or database access.

  4. Development speed, build time. To be most useful, inline d code has to be visible to the caller, which means that the caller has to depend on the internals of the inline d code. Depending on another module's internal implementation details increases the practical coupling of modules (it does not, however, increase their theoretical coupling, because the caller doesn't actually use any of the callee's internals). Usually, when functions change, callers do not need to be recompiled, only relinked. When inline d functions change, callers are forced to recompile. What's more, there's a completely separate hit on development speed that appears at debugging time, because stepping into inlined functions and managing breakpoints inside them tends to be more difficult for most debuggers .

    There is one case in which inlining a function can arguably be viewed as an optimization for development speed ”when the cost of writing an accessor function (see below) would otherwise be too high to justify the good practice of providing an accessor function to avoid making a data member public. In this case, some would argue that inline encourages good coding style and better module insulation.

Finally, if you're looking to improve efficiency in some way, always look to your algorithms and data structures first. They will give you the order-of-magnitude overall improvements, whereas process optimizations, such as inlining, generally (note, generally ) yield less-dramatic results.

Just Say "No for Now"

3. When and how should you decide to inline a function?

The answer is the same as when to apply any other optimization: after a profiler tells you to, and not a minute sooner. There are a few valid exceptions to this guideline for cases in which you would reasonably inline right away, such as for an empty function that's likely to stay empty, or when you're absolutely forced to ”for example, when writing a non-exported template.

Guideline

graphics/guideline.gif

The first rule of optimization: Don't do it.

The second rule of optimization: Don't do it yet.


Bottom line, inlining always costs something, if only increased coupling, and you should never pay for something until you know you're going to turn a profit ”that is, get something better in return.

"But I can always tell where the bottlenecks are," you may think. Don't worry, you're not alone. Most programmers think this at one time or another, but they're still wrong. Dead wrong. Programmers are notoriously poor guessers about where their code's true bottlenecks lie. Sometimes, we get lucky and are right. Most of the time, we're not.

Usually, only experimental evidence (a.k.a. profiling output) helps to tell you where the true hot spots are. Nine times out of ten, a programmer cannot identify the number-one hot-spot bottleneck in his or her code without some sort of profiling tool. In my years in this business, I've come across several programmers who have protested until they (or their colleagues) were blue in the face that this didn't apply to them, that they could consistently "feel" where the hot spots were in their code. In those same years , I've never seen such a claim turn out to be consistently true. We're good at fooling ourselves .

Finally, note another practical reason for this: Profilers are a lot less good at identifying which in lined functions should not be in lined.

What About Computation-Intensive Tasks (Such as Numeric Libraries)?

Some people write small, tight library code, such as advanced scientific and engineering numerical libraries, and can do reasonably well with seat-of-the-pants inlining. Even those developers, however, tend to inline judiciously and to tune later rather than earlier. Note that writing a module and then comparing performance with "inlining on" and "inlining off" is generally an unsound idea, because "all on" or "all off" is a coarse measure that tells you only about the average case. It doesn't tell you which functions benefited, nor how much each one benefited. Even in these cases, you're usually better off to use a profiler and to optimize based on its advice.

What About Accessors?

There are people who will argue that one-line accessor functions (like " X& Y::f(){ return myX_; } ") are a reasonable exception and could or should be automatically inlined. I understand the reasoning, but be careful. At the very least, all inlined code increases coupling. So, unless you're certain in advance that inlining will help, there's no harm in deferring that decision to profiling time. If at that point, a profiler does point out that inlining will help, at least you know that what you're doing is worth doing, and you've deferred the coupling and possible build overhead until you know it will really matter. Not a bad deal, that.

Guideline

graphics/guideline.gif

Avoid inlining or detailed tuning until performance profiles prove the need.


I l @ ve RuBoard


More Exceptional C++
More Exceptional C++: 40 New Engineering Puzzles, Programming Problems, and Solutions
ISBN: 020170434X
EAN: 2147483647
Year: 2001
Pages: 118
Authors: Herb Sutter

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net