在Java中禁用System.out以获得速度

时间:2012-03-27 02:14:13

标签: java system.out

我正在用java编写一个模拟重力的程序,在其中我有一堆日志语句(到System.out)。我的程序运行速度很慢,我认为日志记录可能是其中一部分原因。有没有办法禁用System.out,以便我的程序在打印时不会变慢,或者我是否必须手动浏览并注释/取消注释每个程序以启用/禁用调试语句?任何帮助,将不胜感激。

10 个答案:

答案 0 :(得分:15)

输出流gobbler再次起作用,可能就像......

  System.setOut(new PrintStream(new OutputStream() {

     @Override
     public void write(int arg0) throws IOException {

     }
  }));

但更好的解决方案是使用已经提到的正式日志记录实用程序。

答案 1 :(得分:12)

您应该使用真实的日志记录框架,例如log4jslf4j。在任何一种情况下,您都可以设置日志记录级别,以限制转储到日志中的信息级别。

如果您坚持使用System.out,则可以将日志记录语句包装在一个条件中,例如

if (DEBUG) {
  System.out.println(...);
}

是的,对System.out进行大量日志记录或打印会影响性能。

答案 2 :(得分:4)

我同意其他人应该使用合适的记录器。然而,在每种情况下都不可能。 OP询问以下代码禁用快速

System.setOut(new java.io.PrintStream(new java.io.OutputStream() {
    @Override public void write(int b) {}
}) {
    @Override public void flush() {}
    @Override public void close() {}
    @Override public void write(int b) {}
    @Override public void write(byte[] b) {}
    @Override public void write(byte[] buf, int off, int len) {}
    @Override public void print(boolean b) {}
    @Override public void print(char c) {}
    @Override public void print(int i) {}
    @Override public void print(long l) {}
    @Override public void print(float f) {}
    @Override public void print(double d) {}
    @Override public void print(char[] s) {}
    @Override public void print(String s) {}
    @Override public void print(Object obj) {}
    @Override public void println() {}
    @Override public void println(boolean x) {}
    @Override public void println(char x) {}
    @Override public void println(int x) {}
    @Override public void println(long x) {}
    @Override public void println(float x) {}
    @Override public void println(double x) {}
    @Override public void println(char[] x) {}
    @Override public void println(String x) {}
    @Override public void println(Object x) {}
    @Override public java.io.PrintStream printf(String format, Object... args) { return this; }
    @Override public java.io.PrintStream printf(java.util.Locale l, String format, Object... args) { return this; }
    @Override public java.io.PrintStream format(String format, Object... args) { return this; }
    @Override public java.io.PrintStream format(java.util.Locale l, String format, Object... args) { return this; }
    @Override public java.io.PrintStream append(CharSequence csq) { return this; }
    @Override public java.io.PrintStream append(CharSequence csq, int start, int end) { return this; }
    @Override public java.io.PrintStream append(char c) { return this; }
});

我的样本测量结果如下:

  • 82ms全面输出
  • 仅覆盖write(int)
  • OutputStream的57毫秒
  • 31ms时覆盖PrintStream方法
  • 注释掉所有printlnprintf用法时,
  • 5ms

所以它比其他答案更快,但不能打败不存在的代码(注释System.out或包装if (DEBUG)),因为varargs分配数组和框原语或{{1 (StringBuilder)仍然执行。

答案 3 :(得分:3)

绝对开始使用日志API而不是System.out。我强烈推荐Logback。您可以轻松设置只记录到控制台的内容,但可以随时关闭。 Logback很容易配置,但是如果你不喜欢配置文件,你甚至可以通过编程方式设置它。

Log4j也很好,它是与Logback相同的作者的早期框架,被许多人认为是标准。 SLF4J,同一作者再一次,不是真正的日志框架,而是抽象实际日志记录实现的标准包装器。 Log4j可以包装在SLF4J中,而Logback具有本机SLF4J接口。如果我是你,我会为various reasons避免使用Apache Commons Logging。我从未成为内置Java日志记录的忠实粉丝(java.util.logging)。

答案 4 :(得分:2)

如果你不介意只通过一次,你可以创建一个“启用”或“禁用”的常量,并添加一个标志,只有在启用该常量时才打印。然后你可以轻松地翻转常数。

public static boolean PRINTLN_ENABLED = true;

if(Constant.PRINTLN_ENABLED)
    System.out.println();

答案 5 :(得分:2)

我建议您将来查看log4j(或类似的库)。它的工作方式与system.out相同,但实际上可以在需要时关闭它们。

答案 6 :(得分:2)

如果您的应用程序是在命令行启动的,则可以在操作系统级别禁用整个程序的stdout流。这将有效地禁用所有System.out.prinln(),而无需您更改任何代码。

在Linux / Unix上,您可以通过将stdout重定向到/ dev / null来关闭它:java MyJavaProgram > /dev/null

答案 7 :(得分:1)

由于您在其中一条评论中提到了Eclipse,因此您可以在此处找到相关答案:https://stackoverflow.com/a/799277/1017130

(我最初想发布这个作为对shj答案的评论,但似乎我需要更多的代表)

最好的长期解决方案是使用日志框架。我通常使用内置日志记录,因为我试图避免额外的依赖。您可以在此处详细了解:http://docs.oracle.com/javase/1.4.2/docs/guide/util/logging/overview.html

答案 8 :(得分:0)

我怀疑你可以使用System.setOut(PrintStream)委托一个没有做任何事情的PrintStream,但这可能不会消除你所有的开销 - 我怀疑,例如,格式化错误消息仍然会花费你。

答案 9 :(得分:0)

我已将此代码放入我的Web项目中的查找侦听器中并解决了问题

  /*
     * In this case, if you are not in debug mode or any other 
     *the default system out is replaced internally with this
     *implementation, else it works as expected. This way you do not 
     *have to find and replace anything in your code.
     */
//or as i did servletContext.getInitParameter("mode") 
//from web.xml for global parameter

        if(!DEBUG) {
        System.setOut(
            new PrintStream(new OutputStream() { 
                public  void    close() {}
                public  void    flush() {}
                public  void    write(byte[] b) {}
                public  void    write(byte[] b, int off, int len) {}
                public  void    write(int b) {}

            } );
        }
    }