I had to define a new set of wrappers for existing methods.
These new wrappers intend to help in debugging by including certain tracing information.
Original Source Code:
Sample.c ::
Caller{
void functionA(){
funcB();
}
}
Callee{
void funcB(){
}
}
Modified Code with Traditional Wrapper Functionality:
Sample.h ::
#define funcB wrapperFuncB //not visible to Callee
Caller{
void functionA(){ //this gets redirected to wrapperFuncB cos of #define
funcB();
}
}
Callee{
void wrapperFuncB(){
if(DEBUG){ //value of DEBUG is set at runtime
//COLLECT Trace data
}else{
funcB();
}
}
void funcB(){
}
}
This mechanism has the additional overhead of :
1] All calls to funcB is routed to wrapperFuncB, irrespecitve of DEBUG enabled or not
2] An additional method frame [wrapperFuncB] has to be created, irrespecitve of DEBUG enabled or not
3] An overhead of a conditional check
If the methods are identical, you could use something like this:
#ifdef __DEBUGING
#define myClass debug_class
#else
#define myClass actual_class
#endif
In this way, you can selectively choose which class you are using in your code, the actual one or the wrapper one. There may be a few problems though, because this was just the first idea that came to mind.
Alternatively you could put your debug statements like this
#ifdef DEBUG_ENABLE
DEBUG_LOG(X) printf(x)
#else
DEBUG_LOG(X) do{}while(0)
void FunctionA()
{
DEBUG_LOG("\n Debugging function",__func__);
}
You can use the same routine without wrappers. Advantage would be the logs would make the code little bit easier to understand and you can enable and disable them using the compiler options.
As function wrapperFuncB will have the same signature as funcB, you can simply do this without the need of a new class.
#ifdef __DEBUG__
#define funcB wrapperFuncB
#else
#define funcB actualFuncB
#end
so when you are not debugging or collecting trace info, you can simply turn it off by not defining DEBUG and there will be no overhead
Edit: Updated after getting comments from user170008
I dont think #ifdef __DEBUG__ kind of thing can be used at run time. Most probably you will have to rely on command line params to differentiate between a debug or normal run.
But what ever way you use just create a function pointer and set it according to what kind of run you are doing e.g
void (*funcB)(void);
if(debug)
funcB=debugFuncB;
else
funcB=actualFuncB;
after this you can simply use funcB as you are using now i.e funcB();
Related
In the code base I have many sections that are either turned on or off depending on enabled features. The aim is to generate program code as small as possible (Arduino with 32kB program memory).
Lets say I have the code as below:
class A
{
private:
#ifdef FEATURE
int m_optA;
int m_optB;
#endif
public:
#ifdef FEATURE
void SetFeatureOptions(int optionA, int optionB)
{
m_optA = optionA;
m_optB = optionB;
}
#endif
};
#ifdef FEATURE
#define SETFEATUREOPTIONS(a, b) SetFeatureOptions(a, b)
#else
#define SETFEATUREOPTIONS(a, b) Noop() // ????? <-- what should I put here to perform NOOP
#endif
class B
{
public:
A m_a;
void DoStuff()
{
// approach 1:
#ifdef FEATURE
m_a.SetFeatureOptions(1, 34);
#endif
// approach 2:
// Lets have a macro - see above
// This way each time I want to call SetFeatureOptions but only when FEATURE is defined
// I need no ifdef/endif scope to be used explicitely.
m_a.SETFEATUREOPTIONS(1, 34);
}
}
Is there a way to resolve SETFEATUREOPTIONS macro so it compiles and yet doesn't generate any code, when called as a method name?
Why way is to implement Noop() method in class A, but I was wondering if there is better way, that is not requiring adding a null method like mentioned above Noop(). I am not sure if adding inline Noop(){} will add some bytes to the program memory or not (Release, optimized code).
IMPORTANT: This has to compile with C++98 compiler.
Just write:
void SetFeatureOptions(int optionA, int optionB)
{
#ifdef FEATURE
m_optA = optionA;
m_optB = optionB;
#endif
}
and make sure you compile with optimizations turned on. Your compiler is smart enough to delete the function call, if the function is defined in the header file and is empty.
If the function is defined in a different .cpp file the compiler won't know it's empty, so it won't delete the call.
I usually use the #define macro to add code that will be here while compiling as debug time and not while compiling as release. For instance:
#ifdef NDEBUG
# define LOG(msg) (void)msg
#else
# define LOG(msg) MyDebugLogger(msg)
#endif
Instead of that, I was thinking of using plain function and, just not providing the body for the release method:
void MyDebugLogger(std::string const& msg);
In MyDebugLogger.cpp:
void MyDebugLogger(std::string const& msg)
{
#ifdef NDEBUG
std::clog << msg << "\n"; // Or whatever
#else
(void)msg;
#endif
}
I'm expecting that the compilers will have the power to strip out the call and add no extra cost in Release. Am I correct?
For some reason, could it be a bad practice?
EDIT: My question is: If I use macros as before, I know that in Release mode, the executable will be smaller and faster, as all the code has been removed.
If I use the function, will it be the same? As the compiler may understand that the function does nothing and is not necessary. (Or it will add an extra, even small, for calling an empty function)
practically you would do the same as with the macro:
void MyDebugLogger(std::string const& msg)
{
#ifdef NDEBUG
std::clog << msg << "\n"; // Or whatever
#endif
}
You'r example should work, with a little tweak. In your current version the compiler "sees" just the function signature and will emit a call to it's symbol, which will later be resolved via the linker, so it can't optimize it out on it's own. (Link Time Optimizations might help with that, but that depends very much on you'r setup and dynamic linking would make this impossible). So maybe try something like this
in the header:
// Assuming you are using clang or gcc,
// but is required to not give an error by the standard and probably
// not even needed.
[[gnu::always_inline]]
void MyDebugLogger(std::string const& msg [[maybe_unused]])
{
#ifdef NDEBUG
MyDebugLoggerImplementation(msg);
#endif
}
And then implement it in you .cpp file. Another benefit of this method is that you
method needs the Logger to be compiled with NDEBUG while this method gives the client code the choice.
Below is an example of using a debug variable
class A{
public:
A(bool debug):m_debug(debug){};
~A(){};
void Test(){
for(int i=0;i<1000000;i++){
// do something
if(m_debug) print();
}
}
void print(){
std::cout << "something" << std::endl;
}
private:
bool m_debug;
};
Below is an example of using a debug macro preprocessor
#include "Preprocessor.h"
class A{
public:
void Test(){
for(int i=0;i<1000000;i++){
// do something
#ifdef DEBUG
print();
#endif
}
}
void print(){
std::cout << "something" << std::endl;
}
};
In Preprocessor.h is simply
#define DEBUG
The good thing about using a debug variable is the class has one less dependency on a global preprocessor header. The good thing about the macro approach is that there are 1000000 less if statement executed at run time, which might be critical for lets say graphics application when every single fps counts. What would be considered as a better approach?
The better approach is to use preprocessor, however, it do not necessary a new header file to define the macro.
You can set the flag at compiling, using -DMACRO_NAME or, in your case, -DDEBUG.
As long as the job is printing debug info, the precedent is to use macros like Visual Studio does (debug/release build). However in Qt world, there is class QLoggingCatagory where you can enable/disable logging sections. It calls the function QLoggingCategory::isDebugEnabled()every time a message is being logged out which makes me think it is not a major issue for performance at least for normal use.
That said if we comapare Visual Studio MFC application with Qt application, MFC applications are lighting fast. This could be attributed at least in part because it uses macros and the difference can be noticed rather easily in debug and release build as well where macro/debug info is the main difference.
Given all this evidence my vote is for macros approach in your case for maximum performance.
First, the macro way is better for both benefits in memory and if testing(though this is really minor cost). Do you have any special scenarios to use the debug variable?
why not define the A::Test() in the CPP file? thus the global preprocessor header could be moved to the CPP file. Anyway, I don't think expose such debug details in the header is a good idea.
Another alternative, if you do not like having a bunch of #ifdef DEBUG / #endif lines, you could create a macro that outputs it's argument if defined (much like the assert macro).
#ifdef DEBUG
#define PRINT(x) (x)
#else
#define PRINT(x)
#endif
PRINT( std::cout << "something" << std::endl );
The code path does not get much more minimal than "compiled away". However, if you are willing to perform a refactoring step, you can make the run-time debug version cheaper at the cost of a larger executable.
The idea is to make the debug state a template parameter of a refactored version of Test() so that it may or may not print a debug statement on each iteration. The compiler's dead code elimination pass will then optimize away the statement in the case false is passed to the template, since template parameters will be treated as compile time constants in the template expansion.
The fully optimized version can still use conditional compilation to always disable debug output, of course.
template <bool Debug>
void TestDebug(){
for(int i=0;i<1000000;i++){
// do something
if (Debug) print();
}
}
void Test(){
#ifdef DEBUG
if(m_debug) TestDebug<true>();
else TestDebug<false>();
#else
TestDebug<false>();
#endif
}
I have a code that runs on an embedded system and it has to run really fast. I know C and macros, and this particular project is coded mostly in C but it also uses C++ templates [increasingly more]. There is an inline function:
inline my_t read_memory(uint32 addr) {
#if (CURRENT_STATE & OPTIMIZE_BITMAP)
return readOptimized(addr);
#else
return MEMORY[addr];
#endif
}
This function reads from memory in an optimized fashion or conventional fashion based on the current state and a bitmap that tells whether to use optimization in a specific state or not.
#define STATE_A 0x0001
#define STATE_B 0x0010
#define STATE_C 0x0100
#define STATE_D 0x1000
#define OPTIMIZE_BITMAP 0x1010 // optimize states d and b
and during the course of execution (ok, compilation), I tried to redefine CURRENT_STATE like so:
int main(){
#define CURRENT_STATE STATE_A
do_a();
#undef CURRENT_STATE
#define CURRENT_STATE STATE_B
do_b();
....
}
All do_X() functions make read_memory() calls. I could not make this approach work. The value of current state is always STATE_A as I can see when I use #warning statements. This is not my question, although if you can help me with this I'll be double happy. So, my question is, is there a way to do this kind of thing using templates instead of macros?
Some more info: I have to use an inline function because I cannot export MEMORY[] and this is a library function. I really prefer not to modify the function prototype (like read_memory()...) but it will do. Also, pardon my obscurity.
many thanks,
The inline function will be parsed once, at the point in the translation unit where it is declared, and the state of the macros at that point will be used. Calling the function multiple times with the macros defined differently will not change the definition of the function.
You can do this with a template though --- if you pass the "current state" as a template parameter then you can use a different instantiation at each call point:
template<unsigned state>
inline my_t read_memory(uint32 addr) {
if(state & OPTIMIZE_BITMAP)
return readOptimized(addr);
else
return MEMORY[addr];
}
int main(){
read_memory<STATE_A>(some_addr);
read_memory<STATE_B>(some_addr);
....
}
The compiler will realise that state & OPTIMIZE_BITMAP is a constant and optimize out one or other branch of the if for each template instantiation.
I think you may be misunderstanding what the compiler (or rather, the preprocessor) does with #defines.
Your example (quoted below) is not useful, because CURRENT_STATE is not used between the #define and the #undef. The preprocessor isn't 'executing' your code, or expanding do_a() inline at this point. #defines and macro expansion can only occur EXACTLY IN THE ORDER OF THE LINES IN YOUR SOURCE.
#define CURRENT_STATE STATE_A
do_a();
#undef CURRENT_STATE
Here's a preprocessor-based solution, if templates fill you with horror. Let's assume that do_a() should use the optimised version.
inline my_t read_memory(uint32 addr)
{
return MEMORY[addr];
}
inline my_t read_memory_optimized(uint32 addr)
{
return readOptimized(addr);
}
Now, create DO_CONFIG.H
#if defined(DO_A) || (defined(DO_C) || ...)
#define READ_MEMORY read_memory_optimized
#else
#define READ_MEMORY read_memory
In DO_A.C, add this at the top
#define DO_A
#include DO_CONFIG.H
...and use x=READ_MEMORY(addr) instead of x=read_memory(addr). To switch from optimised to non-optimised, just change DO_CONFIG.H
I've a very basic class, name it Basic, used in nearly all other files in a bigger project. In some cases, there needs to be debug output, but in release mode, this should not be enabled and be a NOOP.
Currently there is a define in the header, which switches a makro on or off, depending on the setting. So this is definetely a NOOP, when switched off. I'm wondering, if I have the following code, if a compiler (MSVS / gcc) is able to optimize out the function call, so that it is again a NOOP. (By doing that, the switch could be in the .cpp and switching will be much faster, compile/link time wise).
--Header--
void printDebug(const Basic* p);
class Basic {
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
printDebug(this);
}
};
--Source--
// PRINT_DEBUG defined somewhere else or here
#if PRINT_DEBUG
void printDebug(const Basic* p) {
// Lengthy debug print
}
#else
void printDebug(const Basic* p) {}
#endif
As with all questions like this, the answer is - if it really matters to you, try the approach and examine the emitted assembly language.
Compiler possibly may optimize this code, if it knows printDebug function implementation at compilation time. If printDebug is in another object module, this possibly may be optimized only by linker, using the whole program optimization. But the only way to test this is to read compiler-generated Assembly code.
If you already have PRINT_DEBUG macro, you can extend it by the way as TRACE is defined:
#define PRINT_DEBUG // optional
#ifdef PRINT_DEBUG
#define PRINT_DEBUG_CALL(p) printDebug(p)
#else
#define PRINT_DEBUG_CALL(p)
#endif
void printDebug(const Basic* p);
class Basic {
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
PRINT_DEBUG_CALL(this);
}
};
--Source--
// PRINT_DEBUG defined somewhere else or here
#if PRINT_DEBUG
void printDebug(const Basic* p) {
// Lengthy debug print
}
#endif
#if PRINT_DEBUG
#define printDebug _real_print_debug
#else
#define printDebug(...)
#endif
This way the preprocessor will strip all debug code before it even gets to the compiler.
Currently most of the optimizations are done at compile time. Some compilers as LLVM are able to optimize at link time. This is a really interesting idea. I suggest you to take a look at.
Waiting for these kind of optimization, what you can do is the following. Define a macro that let you include the following statement depending on whether DEBUG is defined or not.
#ifdef DEBUG
#define IF_DEBUG (false) {} else
#else
#define IF_DEBUG
#endif
You can the use it like this
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
IF_DEBUG printDebug(this);
}
which is already much more readable than
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
#if DEBUG
printDebug(this);
#endif
}
Note that you can use it as if it was a keyword
IF_DEBUG {
printDebug(this);
printDebug(thas);
}
errm, why not use the pre-processor macro differently?
Just of the top of my head, something like:
#define DEBUG_TRACE(p)
#ifdef PRINT_DEBUG
printDebug(p);
#else
;
#endif