How can I disable System.out for speed in Java
Asked Answered
L

10

15

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?

Lepidosiren answered 27/3, 2012 at 2:14 Comment(4)
I suppose you could create a stream gobbler, redirect the standard output stream to your gobbler and go from there.Runoff
Without refactoring your code, I doubt it.Abaxial
@Did you try writing to /dev/null (if you are on UNIX) or NUL on windows. That should be faster - not sure how much. I expect it to be significantly fasterYoulandayoulton
System.out is not (as you have discovered) a logging API; consider using java.util.logging or one of the many alternatives.Diatomic
J
9

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

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 PrintStream methods as well
  • 5ms when commented out all println and printf usages

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.

Junta answered 17/1, 2016 at 14:3 Comment(3)
Any reason why this doesn't work inside a static block?Nena
Thanks for the solution. Now how do we re-enable system.out at a later point?Suwannee
@Suwannee stdout = System.out and later call System.setOut(stdout)Junta
R
25

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.

Runoff answered 27/3, 2012 at 2:22 Comment(2)
I thought of that, but I think that that would still use up some time when the PrintStream formats the input for the OutputStreamLepidosiren
Logback and other SLF4J-style interfaces provide a decent solution to that issue - the so-called "{}" style of invocation. See this link: slf4j.org/faq.html#logging_performance.Overwrite
E
13

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.

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

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

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

Exsiccate answered 27/3, 2012 at 2:19 Comment(3)
Why do you say that the's no way to turn off System.out when it can in fact be re-directed?Runoff
@HovercraftFullOfEels you can only redirect it to a PrintStream, which will wast almost as much tie formatting it.Lepidosiren
agreed. the original question is "disable system.out". you can't technically disable it. redirecting it may result in less load, but there's still the work of writing to the stream and evaluating the string object(s) to be written.Exsiccate
J
9

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

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 PrintStream methods as well
  • 5ms when commented out all println and printf usages

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.

Junta answered 17/1, 2016 at 14:3 Comment(3)
Any reason why this doesn't work inside a static block?Nena
Thanks for the solution. Now how do we re-enable system.out at a later point?Suwannee
@Suwannee stdout = System.out and later call System.setOut(stdout)Junta
O
3

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.

Log4j is 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).

Overwrite answered 27/3, 2012 at 2:20 Comment(0)
H
3

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.

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

Hellenist answered 27/3, 2012 at 2:43 Comment(3)
It's started from eclipse. Is there any way to do that in eclipse?Lepidosiren
@+1. Original question did not look like eclipse specific. this answer should be listed bit above other answers. (i missed it, hence my comment on nul)Youlandayoulton
In eclipse, open the 'Run Configurations' window, select the 'Common' tab. At the bottom of the window there's a section for handling Standard Input and Output. Deselect 'Allocate console' and it shouldn't output anything to your console anymore. Note that this will disable your ability to use stdin as well.Hellenist
R
2

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 have switches to turn them off when you need to.

Roomette answered 27/3, 2012 at 2:20 Comment(0)
S
1

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();
Spirometer answered 27/3, 2012 at 2:19 Comment(1)
This is works. But it has the problem that to turn logging on and off you have to change the constant in the source code and recompile the class, and every other class that uses that constant. If you replace the constant with something that is not known at compile time, then the test will have to be performed each time, and that represents a small runtime overhead.Defenestration
F
1

Since you mentioned Eclipse in one of your comments you can find a relevant answer here: https://mcmap.net/q/821615/-i-o-redirection-in-eclipse

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

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

Ferris answered 27/3, 2012 at 7:9 Comment(0)
B
0

I suspect you could use System.setOut(PrintStream) to delegate to a PrintStream that 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.

Banna answered 27/3, 2012 at 2:21 Comment(1)
you can only use System.setOut on a PrintStreamLepidosiren
P
0

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

            } );
        }
    }
Postdate answered 14/9, 2013 at 8:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.