2011-12-22 21 views
42

Escuché que usar System.out.println para fines de registro es una práctica muy mala y esto puede forzar al servidor a fallar.No use System.out.println en el código del lado del servidor

No uso este enfoque, pero estoy muy interesado en saber por qué System.out.println podría hacer cosas tan malas cuando se usa en el código back-end.

+3

Creo que la pregunta (o el razonamiento detrás de esto) es mucho más interesante de lo que podría ser la respuesta. – Rekin

Respuesta

41

System.out.println es una operación IO y, por lo tanto, lleva mucho tiempo. El problema con el uso en su código es que su programa esperará hasta que la impresión haya finalizado. Esto puede no ser un problema con sitios pequeños, pero tan pronto como reciba carga o muchas iteraciones, sentirá el dolor.

El mejor enfoque es utilizar un marco de registro. Utilizan una cola de mensajes y escriben solo si no hay otra salida.

Y otra ventaja es que puede configurar archivos de registro separados para diferentes propósitos. Algo por lo que tu equipo de Ops te amará.

leer más aquí:

4

Se considera que es malo porque System.out.println(); come más CPU y, por lo tanto, la salida viene lenta, perjudica el rendimiento. (En realidad, cada operación de E/S come CPU).

+1

Normalmente, el problema principal no es el uso de la CPU, sino el uso de E/S, y el hecho de que 'System.out.println' es [blocking] (http://en.wikipedia.org/wiki/Blocking_I/O) - como la mayoría de las llamadas de E/S en Java (y en la mayoría de los otros entornos). Esto puede matar completamente el rendimiento. – sleske

17

Es una mala práctica porque cuando su aplicación entra en Producción, no puede separar los registros de la aplicación de los registros del servidor.

Los equipos Prod quieren que se separen los registros producidos por la aplicación de los del servidor de la aplicación (tomcat, websphere, etc ...): quieren poder monitorizar el servidor de aplicaciones de forma diferente a la aplicación.

Además, al usar System.out, no puede definir el nivel de registro: en Producción, no desea imprimir información de depuración.

3

La razón no es que el servidor pueda fallar, pero podría ser difícil encontrar tal salida en el servidor. Siempre debe usar algún tipo de estructura de registro con un comportamiento definido y un archivo de salida.

2

Por un lado, tener varias solicitudes de llegar a su servidor e imprimir el registro en System.out no es una buena práctica.

  1. Todos los registros se imprimen en la pantalla (descriptor de archivo). No hay forma de retroceder y leer el registro.
  2. System.out no está sincronizado. Debe haber una administración de concurrencia para administrar la impresión a través de System.out
  3. No puede determinar los niveles de registro a través de System.out. No puede separar sus niveles de registro en salidas separadas sobre la marcha.

Espero que esto ayude.

+0

Acerca del primer punto: es fácil redirigir la salida a un archivo para que se desplace lo que desee. – Jesper

+0

Eso es si canalizas desde la consola, pero eso consume muchos recursos. –

+0

+1 para mencionar el problema de simultaneidad – Kaunteya

13

Salida Adam Biens article en la edición de la revista Java Noviembre/Dezember acerca de las pruebas de estrés aplicaciones JEE6 - está libre online, solo tienes que suscribirte.

En la página 43 muestra que las aplicaciones de servidor que manejan 1700 transacciones por segundo se reducen a solo 800 cuando se inserta una sola System.out.println con una cadena de caracteres en cada una.

+0

+1 para proporcionar realmente los resultados de la medición. – sleske

0

Usar la salida estándar es una mala práctica. Sin embargo, si tiene una biblioteca o código que usa System.out y System.err, puede escribir su propio PrintStream que registra el nombre del hilo y la información() y el error() en su lugar. Una vez que haya hecho esto, puede estar más relajado sobre el uso de System.out, ya que se escribirá en los registros, p. log4j.

Lo ideal sería utilizar los registros adecuados directamente esp para el registro de nivel de depuración. En mi humilde opinión no tiene que importar mucho, siempre que no uses el System.out/err integrado. (Una gran suposición)

Tanto si usa System.out que se redirige a un archivo como si usa log4j o Java Logger para escribir en un archivo, el rendimiento es casi exactamente el mismo.

1

Una razón más es que System.out y err son PrintStreams, que están consumiendo todas las IOExceptions subyacentes. Ver esta métodos de PrintStreams:

/** 
* Writes the specified byte to this stream. If the byte is a newline and 
* automatic flushing is enabled then the <code>flush</code> method will be 
* invoked. 
* 
* <p> Note that the byte is written as given; to write a character that 
* will be translated according to the platform's default character 
* encoding, use the <code>print(char)</code> or <code>println(char)</code> 
* methods. 
* 
* @param b The byte to be written 
* @see #print(char) 
* @see #println(char) 
*/ 
public void write(int b) { 
    try { 
     synchronized (this) { 
      ensureOpen(); 
      out.write(b); 
      if ((b == '\n') && autoFlush) 
       out.flush(); 
     } 
    } 
    catch (InterruptedIOException x) { 
     Thread.currentThread().interrupt(); 
    } 
    catch (IOException x) { 
     trouble = true; 
    } 
} 

/** 
* Flushes the stream and checks its error state. The internal error state 
* is set to <code>true</code> when the underlying output stream throws an 
* <code>IOException</code> other than <code>InterruptedIOException</code>, 
* and when the <code>setError</code> method is invoked. If an operation 
* on the underlying output stream throws an 
* <code>InterruptedIOException</code>, then the <code>PrintStream</code> 
* converts the exception back into an interrupt by doing: 
* <pre> 
*  Thread.currentThread().interrupt(); 
* </pre> 
* or the equivalent. 
* 
* @return <code>true</code> if and only if this stream has encountered an 
*   <code>IOException</code> other than 
*   <code>InterruptedIOException</code>, or the 
*   <code>setError</code> method has been invoked 
*/ 
public boolean checkError() { 
    if (out != null) 
     flush(); 
    if (out instanceof java.io.PrintStream) { 
     PrintStream ps = (PrintStream) out; 
     return ps.checkError(); 
    } 
    return trouble; 
} 

Así que una IOException de la corriente subyacente se consume siempre, y por lo general las personas nunca llaman CheckError el sistema, por lo que ni siquiera están sabiendo que algo sucedió.

2
  1. El programa esperará hasta que finalice la impresión. Los madereros usan la cola de mensajes y escriben solo si no hay otra salida.
  2. System.out.println (SOP) no están hilo de seguridad (es decir, asíncrono) registradores son hilo de seguridad (es decir síncrono)
  3. registradores son altamente configurable a. Formato, Limitar contenido del registro alcanzable por madereros b. múltiple de registro de destino -file, console, DB
  4. Los SOP escriben registros en los archivos de registro del servidor. tenemos que mantener registros de la aplicación separada de registros del servidor, ya que puede conducir a un fallo del servidor
  5. aplicaciones de servidor que gestiona para manejar 1700 transacciones por segundo cae a unos 800 al insertar un solo SOP con una cuerda fija en cada
Cuestiones relacionadas