12

I am wondering what the overhead is of having unused functions in your code.

Say for example you have some debug logging, and you then give most of your objects a ToString() function that is being used in the debug logs.

In a release build that debug logging is not being used. Is it then worth it removing the source code of those ToString() functions? (e.g. via Macro?)

Or do they just make the executable marginally larger and otherwise don't impact performance? e.g. no speed impact? Or does the compiler or linker possibly even remove the functions if they are not used? If the compiler or linker don't remove the code, what if the ToString() functions were defined inline? Presumably it would try to inline the code, and since the function is never called, it would disappear?

I imagine every function needs to be retained in a static lib, but once compiled to an executable, surely a lot of stuff just gets ignored by the linker?

On another note that is roughly similar, if the compiler chooses not to inline an inline function, so that the inline function is defined as function in several compilation units, will the linker chuck away the superfluous definitions and only link one of them at the end?

Thanks

7
  • 2
    It could depend on the compiler and what optimizations its using. Commented May 26, 2011 at 11:12
  • 4
    "Premature optimization is the root of all evil" - Donald Knuth Commented May 26, 2011 at 11:19
  • 9
    I get so tired of the premature optimization mantra. Yes thank you for your help. Also: "Understanding what you are doing might help you do it well." Or do you disagree? Surely an understanding of compilers and linkers isn't bad. But thanks for your input. Commented May 26, 2011 at 11:26
  • 5
    @Maurits: I don't like incomplete quotes. Do not forget the Say 97% of the times in front of this. Commented May 26, 2011 at 11:26
  • 1
    The complete quote seems to be: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil" Commented May 26, 2011 at 11:46

4 Answers 4

5

It depends on the compiler and, I guess, optimization level.

G++ and MSVC++ remove unused inline functions but keep unused non-inline functions. For instance, you use only a small fraction of the STL in a normal program. All unused functions get removed, because they're defined as inline.

GCC on the other hand keeps all functions, even unused inline ones.

Answer to your other question: if a function is somehow defined in multiple compilation units, the linker will frown and refuse to link, unless if it is defined as inline.

Sign up to request clarification or add additional context in comments.

1 Comment

Just re your last sentence: unless it is defined as inline. That should stop your compiler from frowning even though it would frown if it weren't defined inline.
3

1. Regarding Compilers and Linkers

It really depends how you create your executable.

Typically executables are stripped of anything that is not used. Therefore if you link statically (and with the right optimization options) the functions will get removed.

However if you link dynamically, they'll be there, because as far as the library is concerned, they are exported and therefore used.

As for the multiple definitions, it depends if the symbol is weak. If it's weak, the linker picks one of the definitions, otherwise it chokes on it.

Finally, they probably only represent a marginal part of your program.

2. How to solve the issue ?

It's a hard problem, you can always use the preprocessor to remove some stuff, but code that is littered with preprocessor directives is really annoying to read.

Personally, I would not bother... especially because I log in Release too (how else tracking down production issues ?).

A solution could be to define the offending functions in a separate file and not link them in Release. Note: I do not think it works for virtual functions, since they are at least used in the vtable

Comments

2

Linkers do remove duplicate functions and they do remove unreferenced data (the Microsoft linker offers the /OPF:REF and /OPT:ICF switches to tweak these settings).

You are certainly right that in most cases it simply won't matter whether the linker does a good job at dropping stuff that is not needed or redundant - the impact on executable size for a few small functions (as compared to i.e. the sheer amount of code that is generated if you make extensive use of the STL or other template libraries) is minimal.

That said, if you need your executable to be as small as possible (or if you find out that your debugging code really takes most of the image size), #ifdefing everything is the simplest way to enforce certain functions not to be included. It makes the code a bit ugly to read but it has the advantage that you can't accidentally miss few spots of debugging code in your release builds since any attempt to invoke a non-existent function will result in a compiler error.

Another advantage of #ifdef is that it is portable and does not depend on a particular compiler system :-/

2 Comments

Would you then say it is preferable to define such debug tostring functions as inline?
Since the compiler is always free to inline or not inline a function, I tend to use inline only for one purpose: to be able to have function definitions in shared header files. Since this is implicit for member functions defined in class bodies, I wouldn't specify inline. But please note that this is just my personal approach to inline.
0

If you put a non-virtual function in a separate file in a library, and link statically, it should only be added to the executable if it is used. But the only real difference will be in the size of the executable; this could conceivably affect locality, and thus performance, but I'd be very surprised if it ever made a real difference in practice. So generally, I'd say that this technique is not worth the bother in an application. (If you're delivering third party libraries, on the other hand, you definitely want every non-virtual function in a separate file.)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.