Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

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.

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

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();

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.

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

Since you mentioned Eclipse in one of your comments you can find a relevant answer here: 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)

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

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.

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

            } );
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top