在 Java 中禁用 System.out 以提高速度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9882487/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 22:45:50  来源:igfitidea点击:

Disable System.out for speed in Java

javasystem.out

提问by Gavin S. Yancey

I'm writing a program in java that simulates gravity, and in it I have a bunch of log statements (to System.out). My program is running really slowly, and I think the logging might be part of the reason. Is there any way to disable System.out, so that my program doesn't slow down when printing, or do I have to manually go through and comment/uncomment each one to enable/disable debug statements? Any help would be appreciated.

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

采纳答案by TWiStErRob

I agree with others that a proper logger should be used. However that is not possible in every case. The following code disablesout and is fastas OP asked:

我同意其他人的看法,即应该使用适当的记录器。然而,这并非在所有情况下都是可能的。以下代码禁用并按照 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; }
});

My sample measurements were:

我的样品测量是:

  • 82ms full blown output
  • 57ms when only overriding write(int)in OutputStream
  • 31ms when overriding PrintStreammethods as well
  • 5ms when commented out all printlnand printfusages
  • 82ms 全开输出
  • 当只覆盖57mswrite(int)OutputStream
  • 覆盖PrintStream方法时也为31 毫秒
  • 5ms 注释掉所有printlnprintf用法

So it is faster than other answers here, but can't beat non-existent code (commenting out System.outs or wrapping in if (DEBUG)) as varargs allocates arrays and boxes primitives or StringBuilder(+too) still executes.

因此,它比此处的其他答案更快,但无法击败不存在的代码(注释掉System.outs 或换行if (DEBUG)),因为 varargs 分配数组和框原语或StringBuilder+也)仍然执行。

回答by Hovercraft Full Of Eels

Again an output stream gobbler could work, something perhaps like...

再次输出流吞噬者可以工作,也许像......

System.setOut(new PrintStream(new OutputStream() {
    @Override
    public void write(int arg0) throws IOException {

    }
}));

But a better solution is to use a formal logging utility as has already been mentioned.

但更好的解决方案是使用前面提到的正式日志实用程序。

回答by Jeffrey Blattman

you should use a real logging framework like log4j, or slf4j. in either case, you can set the logging level, to restrict the level of information being dumped into the logs.

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

if you insist in using System.out, you can wrap your logging statements in a condition, like,

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

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

and yes, heavy logging or printing to System.out will affect performance.

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

回答by sparc_spread

Definitely start using a logging API instead of System.out. I highly recommend Logback. You can easily set up something that just logs to the console but can be switched off anytime. Logback is dead simple to configure, but if you don't like config files you can even set this up programmatically.

绝对开始使用日志 API 而不是System.out. 我强烈推荐Logback。您可以轻松设置一些只登录到控制台但可以随时关闭的内容。Logback 的配置非常简单,但是如果您不喜欢配置文件,您甚至可以以编程方式进行设置。

Log4jis also nice, it is the earlier framework by the same author as Logback, and is considered by many to be the standard. SLF4J, once again by the same author, is not a true logging framework but rather a standard wrapper to abstract the actual logging implementation. Log4j can be wrapped in SLF4J, and Logback has a native SLF4J interface. If I were you I would avoid Apache Commons Logging, for various reasons. I've never been a huge fan of the built-in Java logging (java.util.logging).

Log4j也不错,它是与 Logback 同一作者的早期框架,被许多人认为是标准。 SLF4J再次出自同一作者,它不是真正的日志框架,而是用于抽象实际日志实现的标准包装器。Log4j 可以封装在 SLF4J 中,Logback 有原生的 SLF4J 接口。如果我是你,我会出于各种原因避免使用 Apache Commons Logging 。我从来都不是内置 Java 日志记录 ( java.util.logging) 的忠实粉丝。

回答by d33j

I would suggest that you look into log4j (or similar libraries) in the future. It works the same way as system.out's but actually haveswitches to turn them off when you need to.

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

回答by DavidB

If you don't mind going through all of them just once, you could create a constant that "enables" or "disables" and add a flag to only print if that constant is enabled. Then you can easily just flip the constant.

如果您不介意一次完成所有这些,您可以创建一个“启用”或“禁用”的常量,并添加一个标志以仅在启用该常量时打印。然后你可以轻松地翻转常量。

public static boolean PRINTLN_ENABLED = true;

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

回答by shj

If your application is started at the command-line, you can disable the stdout stream for the entire program at the OS level. This would effectively disable all of your System.out.prinln()s without requiring you to change any of the code.

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

On Linux/Unix you can close stdout by redirecting it to /dev/null: java MyJavaProgram > /dev/null

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

回答by Filip

Since you mentioned Eclipse in one of your comments you can find a relevant answer here: https://stackoverflow.com/a/799277/1017130

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

(I initially wanted to post this as a comment to shj's answer but it seems i need more rep first)

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

The best long-term solution would be to use a logging framework. I generally use the built-in logging, since i try to avoid extra dependencies. You can read more about it here: http://docs.oracle.com/javase/1.4.2/docs/guide/util/logging/overview.html

最好的长期解决方案是使用日志框架。我通常使用内置日志记录,因为我尽量避免额外的依赖。您可以在此处阅读更多相关信息:http: //docs.oracle.com/javase/1.4.2/docs/guide/util/logging/overview.html

回答by shareef

i have put this code once in lookup listener in my web project and solved the problem

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

  /*
     * 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) {}

            } );
        }
    }

回答by Louis Wasserman

I suspect you could use System.setOut(PrintStream)to delegate to a PrintStreamthat doesn't do anything, but that probably won't eliminate all of your overhead -- I suspect, for example, that the formatting of the error messages will still cost you.

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