优化判断日志是否需要输出的性能

一般的软件系统可以根据日志的不同级别控制日志的输出。当用户设置只输出错误的日志信息时,则有大量的告警、通知和调试的日志信息不会输出。由于有大量信息未输出,是否存在优化程序性能的可能呢?我们先来看看通常的日志是如何处理的。

在程序实现时,通常给每条日志赋于一定的级别,一般分为emerg、 alert、crit、err、warning、notice、info和debug等依次增高8个级别。然后我们在日志输出函数内部判断该日志级别是否不高于当前可输出日志级别,若不高于,则输出该日志,否则忽略该日志信息。如程序1 my_log.h和程序2 my_log.c所示,为简单起见,在此以日志在屏幕上输出为例说明。

#ifndef MY_LOG_H
#define MY_LOG_H

// loglevel
enum {
MY_LOG_EMERG = 0, /* system is unusable */
MY_LOG_ALERT, /* action must be taken immediately */
MY_LOG_CRIT, /* critical conditions */
MY_LOG_ERR, /* error conditions */
MY_LOG_WARNING, /* warning conditions */
MY_LOG_NOTICE, /* normal but significant condition */
MY_LOG_INFO, /* informational */
MY_LOG_DEBUG /* debug-level messages */
};

// 设置可日志输出级别
void my_set_log_levels(int level);

// 日志处理函数
void my_log(int level, const char *fmt, ...);

#endif //MY_LOG_H
程序1: my_log.h

#include <stdio.h>
#include <stdarg.h>
#include "my_log.h"

int __my_allow_log_level = MY_LOG_EMERG;

void my_set_log_levels(int level)
{
__my_allow_log_level = level;
}

void my_log(int level, const char *fmt, ...)
{
if( level <= __my_allow_log_level )
{
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
}
程序2: my_log.c

显而易见,在上述的程序2中,调用日志处理函数my_log输出日志时,不管日志根据用户设定是否需要输出,都要进行一次函数调用。在该函数执行过程中,才根据当前可输出日志级别判断该日志是否需要输出。若不需要输出,就立即退出该函数。也就是说,无论日志是否需要输出,程序都将进行一次函数调用。

在写文[1]的过程中,本人受到启发。日志输出和调试信息输出属于同类问题,都是可选择输出某级别以下的信息,而高于该级别的信息不输出。那么我们可以和调试信息输出一样,为了改进程序效率,可以将判断日志是否需要输出移至函数my_log外执行(如程序3和程序4 所示)。这样,先通过if语句判断是否需要输出日志,若需要输出,才调用函数__my_log输出日志,从而提高整个程序的执行性能。

#ifndef MY_LOG_H
#define MY_LOG_H

// loglevel
enum {
MY_LOG_EMERG = 0, /* system is unusable */
MY_LOG_ALERT, /* action must be taken immediately */
MY_LOG_CRIT, /* critical conditions */
MY_LOG_ERR, /* error conditions */
MY_LOG_WARNING, /* warning conditions */
MY_LOG_NOTICE, /* normal but significant condition */
MY_LOG_INFO, /* informational */
MY_LOG_DEBUG /* debug-level messages */
};

// 非log.c文件的外部变量声明
#ifndef MY_LOG_C
extern int __my_allow_log_level;
#endif

// (内部使用) 判断"SECTION"代码段是否允许"DEBUG_LEVEL"级的调试信息输出
#define __my_allow_log(LOG_LEVEL) /
( LOG_LEVEL <= __my_allow_log_level )

// (内部使用)实际的日志输出函数
void __my_log(int level, const char *fmt, ...);

// 设置可日志输出级别
void my_set_log_levels(int level);

// 日志处理函数
#define my_log(LEVEL, FMT, ARG...) /
if( __my_allow_log(LEVEL) ) __my_log(LEVEL, FMT, ##ARG)

#endif //MY_LOG_H
程序3: 改进后的my_log.h

#include <stdio.h>
#include <stdarg.h>
#include "my_log.h"

int __my_allow_log_level = MY_LOG_EMERG;

void my_set_log_levels(int level)
{
__my_allow_log_level = level;
}

void __my_log(int level, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
程序4: 改进后的my_log.c

同样,也可以和文[1]中描述的为每个程序模块设定不同的调试信息显示等级一样,为每个程序模块设定不同的日志输出级别,本文就不再累赘了。

参考文献:

[1] C语言中几种输出调试信息的方法, http://blog.csdn.net/thinkerABC/archive/2006/03/04/615378.aspx , 2006.03.04

你可能感兴趣的:(c,优化,list,System,action,语言)