对已编译的jar进行简单的性能修改?

时间:2009-10-22 13:36:52

标签: java performance jar

与许多log4j用户一样,我们经常进行调试级别日志记录,评估成本很高。因此,我们使用以下代码保护这些案例:

if( _logger.isDebugEnabled )
  _logger.debug("Interesting, my foojes are goofed up: " + getFullDetails())

然而,这比普通的_logger.debug调用更难,有时程序员没有意识到评估可能会很昂贵。

编写一个带有编译jar的程序并使用isDebugEnabled检查保护所有_logger.debug调用似乎应该相当简单。我们可能愿意接受在所有情况下检查isDebugEnabled的额外开销。

有没有人尝试过这种方法,或者对jar进行类似的后期处理?

3 个答案:

答案 0 :(得分:4)

我没有考虑修改jar,而是使用Bytecode Instrumentation搜索解决方案。问题是识别要包含在.isDebugEnabled()内的代码的那些部分 - 您必须识别仅用于log4j调用的对象。

答案 1 :(得分:2)

你看过AspectJ了吗?这支持使用字节码编织的方面,并且可以拦截into a previously compiled .jar file

答案 2 :(得分:1)

我相信一个好的解决方案就是代码效率很高

考虑不推荐使用log4j。它的作者本身保留原样,以避免破坏兼容性,但他创建了一个新的SLF4J(http://www.slf4j.org/)。根据commons-logging / log4j的区别,他提供了一个外观和一个实现,但没有每个的缺陷......

我相信,在这个新的日志记录工具中,您可以将Object参数发送到日志记录,并在转换Objects(到String或其他)之前评估级别。我们的想法是使用格式字符串和参数。


我们的代码不使用slf4j,但是我们有实用的方法就是这样。 它的编码大致如下(来自记忆):

    public enum LogLevel {
       FATAL, ERROR, WARNING, INFO, DEBUG;

       public void log(Logger logger, String format, Object... parameters) {
         if (isEnabled(logger)) {
            logImpl(logger, String.format(format, parameters));
         }
       }
       public boolean isEnabled(Logger logger) {
         switch(this) {
           case WARNING : return logger.isWarningEnabled();
           case INFO : return logger.isInfoEnabled();
           case DEBUG : return logger.isDebugEnabled();
           default: return true;
         }
       }
       private void logImpl(Logger logger, String message) {
         switch(this) {
           case WARNING : logger.warn(message);
           // other cases
         }
       }
    }

用作:

     public void myMethod(Object param) {
       LogLevel.WARNING.log(LOGGER, "What is my message ....", "myMethod", param);
     }

更新:如果您需要在日志中调用方法...

  • 一种可能性是使用toString方法。如果您的日志记录是“技术性”,这是合适的,并且在调试时也会使用。

  • 如果您的日志记录功能更强(不针对开发者),我建议定义一个接口(在这种情况下功能合理,因此提供意义很有用) :

    public interface Detailable { // the name could also suggest logging?
      String getFullDetails();
    }
    

    在任何需要作为日志记录对象传递的对象中实现该接口,并使用复杂的计算来构建日志。