logging optimization

N

Neo

Hi Friends,
My product has a feature of logging. Currently it is simple MACRO
based where during release build compiler removes logging function
calls. Now I am planning to make logging available during release
build as well. As a result user will simply pass some command line
parameter during process start and things will start logging.

Now as this code will be present in my binary during release time,
this will enforce some types of checks even if the logging is not
enabled which will lead to some CPU cost.

Is there any way to optimize these checks?
Are there any way where I can bypass these checks during normal
functional behavior.

Assembly, C, C++ compiler/code specific suggestions are welcome.

- Vikram S
 
I

Ian Collins

Neo said:
Hi Friends,
My product has a feature of logging. Currently it is simple MACRO
based where during release build compiler removes logging function
calls. Now I am planning to make logging available during release
build as well. As a result user will simply pass some command line
parameter during process start and things will start logging.

Now as this code will be present in my binary during release time,
this will enforce some types of checks even if the logging is not
enabled which will lead to some CPU cost.

Is there any way to optimize these checks?

Has profiling shown these to be an issue? If not, you are looking for
premature optimisations.
 
G

Guest

  My product has a feature of logging. Currently it is simple MACRO
based where during release build compiler removes logging function
calls. Now I am planning to make logging available during release
build as well. As a result user will simply pass some command line
parameter during process start and things will start logging.

Now as this code will be present in my binary during release time,
this will enforce some types of checks even if the logging is not
enabled which will lead to some CPU cost.

can you separate logging from checking?

Your code may look like this

#ifdef DEBUG
check_something();
log_something();
#endif

when, perhaps, it should look like

#ifdef CHECK_ON
check_something();
#endif
#ifdef LOG_ON
log_something();
#endif
 
L

lndresnick

Hi Friends,
  My product has a feature of logging. Currently it is simple MACRO
based where during release build compiler removes logging function
calls. Now I am planning to make logging available during release
build as well. As a result user will simply pass some command line
parameter during process start and things will start logging.

Now as this code will be present in my binary during release time,
this will enforce some types of checks even if the logging is not
enabled which will lead to some CPU cost.

Is there any way to optimize these checks?
Are there any way where I can bypass these checks during normal
functional behavior.

Assembly, C, C++ compiler/code specific suggestions are welcome.

- Vikram S

No, you can't have it for free. But how about this? Yes, function
macros are somewhat evil (and this is varargs macro, C99, can do
different ways in C89), but this approach seems like it might work for
your desire for cheapness. First time through it sees if logging is
on for the given tag. All other times the "overhead" is just checking
a static variable. Or if you don't have different levels of debugging
(error vs info type things) can omit tag and checkEnabled just returns
whether logging is on or off globablly.

#define LOG_IT(tag,msg,...) \
{ static int enabled = checkEnabled(tag); \
if (enabled) { \
log(msg, __VA_ARGS__); \
} \
}

-David
 
N

Nelu

Now as this code will be present in my binary during release time,
this will enforce some types of checks even if the logging is not
enabled which will lead to some CPU cost.

Is there any way to optimize these checks?
Are there any way where I can bypass these checks during normal
functional behavior.

Delegate.

Use pointers to functions for the log types and messages that you want and
provide default, empty calls. The application can initialize the function
pointers once at the beginning of the application based on the log settings
you provide (depending on your needs).

e.g.:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void (*log1)(int level, char *msg);

void default_log1(int level, char *msg) {}

void stdout_log1(int level, char *msg) {
printf("%d\t%s\n",level,msg);
}


int main(int argc, char **argv) {
if(argc>1) {
if(strcmp(argv[1],"stdoutlog")==0) {
log1=stdout_log1;
} else {
log1=default_log1;
}
} else {
perror(":( - I need more arguments");
return EXIT_FAILURE;
}
log1(5,"Can you see this?");
return 0;
}
 
N

Neo

Now as this code will be present in my binary during release time,
this will enforce some types of checks even if the logging is not
enabled which will lead to some CPU cost.
Is there any way to optimize these checks?
Are there any way where I can bypass these checks during normal
functional behavior.

Delegate.

Use pointers to functions for the log types and messages that you want and
provide default, empty calls. The application can initialize the function
pointers once at the beginning of the application based on the log settings
you provide (depending on your needs).

e.g.:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void (*log1)(int level, char *msg);

void default_log1(int level, char *msg) {}

void stdout_log1(int level, char *msg) {
    printf("%d\t%s\n",level,msg);

}

int main(int argc, char **argv) {
    if(argc>1) {
        if(strcmp(argv[1],"stdoutlog")==0) {
            log1=stdout_log1;
        } else {
            log1=default_log1;
        }
    } else {
        perror(":( - I need more arguments");
        return EXIT_FAILURE;
    }
    log1(5,"Can you see this?");
    return 0;

}

Well. Thanks to ALL for the useful repiles !
 
D

David Thompson

No, you can't have it for free. But how about this? Yes, function
macros are somewhat evil (and this is varargs macro, C99, can do
different ways in C89), but this approach seems like it might work for
your desire for cheapness. First time through it sees if logging is
on for the given tag. All other times the "overhead" is just checking
a static variable. Or if you don't have different levels of debugging
(error vs info type things) can omit tag and checkEnabled just returns
whether logging is on or off globablly.

#define LOG_IT(tag,msg,...) \
{ static int enabled = checkEnabled(tag); \
if (enabled) { \
log(msg, __VA_ARGS__); \
} \
}
Not in C. The initializer for a static-duration variable, even a local
one, must be a constant (= compiletime) expression.

<OT> C++ does allow this. It has two phases of initialization of
statics. The first corresponds (roughly) to what is allowed in C, and
like C occurs at program loading/startup, as closely as that can be
specified in Standardese without talking about implementation. The
second allows any runtime expression, executed first time 'hit'. </>

In C you can do the equivalent manually, like:
static int enabled = UNINIT;
if( enabled == UNINIT ) enabled = checkEnabled (tag);
if( enabled ) log (...);
For a boolean I like UNINIT=-1 vs 0=false 1=true.
For more general things, I might use -99 or INT_MIN or such.

Of course this does incur the full overhead on the first occurrence of
each invocation-site that is used at all. If there is a large number
of sites (many/most used) that share a fairly small set of flags to
control them (in big groups), which is what I usually do, I think
you're (or I'm) better off just putting the settings in a small global
variable (often as small as bits of one word).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top