Log4j使用的效率二

1、效率

log4j关闭debug级别输出,但是在代码中log.debug(Object msg)的写法不同,将会多耗费3-5倍的时间。因此,要优化log.debug()这个方法的调用的,log.info()也是同理

2、log4j的优化简介

log4j做了大量的优化,比如:Log4j初始化时打开文件并保持对文件的写控制,直到进程结束时才关闭流。这样控制打开I/O次数

还有其他方面的优化,使用了大量缓存,参看debug方法源码

  public void debug(Object message) {
    if(repository.isDisabled(Level.DEBUG_INT))
      return;
    if(Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel())) {
      forcedLog(FQCN, Level.DEBUG, message, null);
    }
  }

设置输出级别为INFO时,调用debug()会直接返回。但在使用LOG.debug("business is" + xxxObj)时,虚拟机在debug方法执行前需要先将字符串进行连接,这就是俺们需要优化的地方。

3、效率编码及测试

下面上干货,fuck goods

测试工具类TestUtil 

package util;

public class TestUtil {
	/**
	 * 
	 * 测试函数使用时间,通过定义TestCallBack接口的execute方法
	 * 
	 * @param testCallBack
	 */
	public static long testTime(TestCallBack testCallBack) {
		long begin = System.currentTimeMillis(); // 测试起始时间
		testCallBack.execute(); // /进行回调操作
		long end = System.currentTimeMillis(); // 测试结束时间
		long cost = (end - begin);
		return cost;
	}
}

 回调函数

package util;

public interface TestCallBack {
	public void  execute();
}

 测试主类

package util;

import org.apache.log4j.Logger;

import util.TestCallBack;
import util.TestUtil;

public class EfficientTest {
	private final static Logger LOG = Logger.getLogger(EfficientTest.class);
	private final static int MAX_LOOP = 100 * 1000 * 1000;

	/**
	 * 正常写法
	 */
	public long log() {
		long cost = TestUtil.testTime(new TestCallBack() {
			@Override
			public void execute() {
				for (int i = 0; i < MAX_LOOP; i++) {
					/**
					 * "test" + "abc" + str的写法,会在运行时产生运算
					 */
					String str = "tt";
					LOG.debug("test" + "abc" + str);
					/**
					 * "test" + "abc"的写法,虚拟机在编译器会合并直接量,运行时并不会运算
					 */
					// LOG.debug("test" + "abc");
				}
			}
		});
		System.out.println("          cost:" + cost);
		return cost;
	}

	/**
	 * 效率写法
	 */
	public long logEfficient() {
		long cost = TestUtil.testTime(new TestCallBack() {
			@Override
			public void execute() {
				for (int i = 0; i < MAX_LOOP; i++) {
					if (LOG.isDebugEnabled()) {
						String str = "tt";
						LOG.debug("test" + "abc" + str);
						// LOG.debug("test" + "abc");
					}
				}
			}
		});
		System.out.println("efficient cost:" + cost);
		return cost;
	}

	public static void main(String[] args) {
		EfficientTest test = new EfficientTest();
		for (int i = 0; i <= 9; i++) {
			System.out.println("====我是华丽的分割线====" + i);
			if (i % 2 > 0) {
				long log = test.log();
				long logEfficient = test.logEfficient();
				System.out.println("log/logEfficient,"
						+ (((double) log / logEfficient) * 100.0)
						+ "% increase");
			} else {
				long logEfficient = test.logEfficient();
				long log = test.log();
				System.out.println("log/logEfficient,"
						+ (((double) log / logEfficient) * 100.0)
						+ "% increase");
			}
			// System.out.println();
		}
	}
}

 log4j配置类,把输出级别调整成INFO级别

log4j.rootCategory=INFO, stdout 

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%p [%t] %C.%M(%L) | %m%n

 运行后的结果

====我是华丽的分割线====0
efficient cost:434
          cost:2054
log/logEfficient,473.2718894009216% increase
====我是华丽的分割线====1
          cost:1822
efficient cost:434
log/logEfficient,419.8156682027649% increase
====我是华丽的分割线====2
efficient cost:394
          cost:1823
log/logEfficient,462.69035532994917% increase
====我是华丽的分割线====3
          cost:1805
efficient cost:400
log/logEfficient,451.25% increase
====我是华丽的分割线====4
efficient cost:400
          cost:1805
log/logEfficient,451.25% increase
====我是华丽的分割线====5
          cost:1790
efficient cost:396
log/logEfficient,452.02020202020196% increase
====我是华丽的分割线====6
efficient cost:397
          cost:1798
log/logEfficient,452.89672544080605% increase
====我是华丽的分割线====7
          cost:1786
efficient cost:393
log/logEfficient,454.45292620865143% increase
====我是华丽的分割线====8
efficient cost:401
          cost:1969
log/logEfficient,491.0224438902743% increase
====我是华丽的分割线====9
          cost:1801
efficient cost:392
log/logEfficient,459.4387755102041% increase

优化效果显而易见,关闭DEBUG级别的日志后,log.debug方法的写法不同,造成运行时间也不同

 

4、类似的方法

除了

LOG.isDebugEnabled()

 还有

LOG.isInfoEnabled()

 还有

LOG.isEnabledFor(Priority.DEBUG);

 

 

 Log4j的HelloWorld 在javaSE中入门使用一

 Log4j使用的效率二

 Log4j的输出格式三

 Log4j将System.out搞到log4j中输出四

你可能感兴趣的:(JAVASE)