socket servidor recibir hilos fuente enviar datos con codigo cliente java performance sockets objectoutputstream objectinputstream

servidor - Problema de rendimiento con Javas Object Streams con Sockets



sockets en java enviar y recibir (5)

Todavía habría pensado que sería más rápido que eso. ¿Hay algo más que pueda hacer para mejorar esto?

Esto parece una especie de micro-punto de referencia. Siempre es difícil hacerlo bien, pero creo que si comienzas enviando decir 2000 mensajes antes de comenzar tus mediciones de latencia.

Además, vea esta respuesta detallada sobre cómo hacer micro-benchmarks correctamente.

Estoy tratando de hacer IPC local utilizando Sockets y secuencias de objetos en Java, sin embargo, veo un bajo rendimiento.

Estoy probando el tiempo de ping de enviar un objeto a través de un ObjectOutputStream para recibir una respuesta a través de un ObjectInputStream en un Socket.

Aquí está el solicitante:

public SocketTest(){ int iterations = 100; try { Socket socket = new Socket("localhost", 1212); ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream()); ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); double start = System.currentTimeMillis(); for (int i = 0; i < iterations; ++i) { Request request = new Request(); objectOutputStream.writeObject(request); Response response = (Response)objectInputStream.readObject(); } double finish = System.currentTimeMillis(); System.out.println("Per ping: " + (finish - start) / iterations ); } catch (Exception e) { e.printStackTrace(); } }

Aquí está el respondedor:

public ServerSocketTest(){ try { ServerSocket serverSocket = new ServerSocket(1212); Socket socket = serverSocket.accept(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream()); Request request = (Request)objectInputStream.readObject(); while (request != null) { Response response = new Response(); objectOutputStream.writeObject(response); request = (Request)objectInputStream.readObject(); } } catch (Exception e) { e.printStackTrace(); } }

El resultado que obtengo es:

Por ping: 80.35

80 mseg está lejos de disminuir para el tráfico local.

Las clases de solicitud y respuesta son muy pequeñas y su serialización es rápida.

He intentado ingenuamente agregando:

socket.setKeepAlive (verdadero);
socket.setTcpNoDelay (verdadero);

con poco efecto.

realizando un ping localhost:

64 bytes de localhost.localdomain (127.0.0.1): icmp_seq = 0 ttl = 64 tiempo = 0.035 ms
64 bytes de localhost.localdomain (127.0.0.1): icmp_seq = 1 ttl = 64 tiempo = 0.037 ms
64 bytes de localhost.localdomain (127.0.0.1): icmp_seq = 2 ttl = 64 tiempo = 0.049 ms
64 bytes de localhost.localdomain (127.0.0.1): icmp_seq = 3 ttl = 64 tiempo = 0.039 ms
64 bytes de localhost.localdomain (127.0.0.1): icmp_seq = 4 ttl = 64 tiempo = 0.056 ms

también es rápido

Java versión 1.6.0_05l ejecutándose en RedHat 2.4

Cualquier idea sería apreciada.



Además de utilizar flujos almacenados en búfer y llamar a flush () antes de cada lectura, también debe crear ObjectOutputStream primero en ambos extremos. Además, la prueba de readObject () devolver nulo no tiene sentido a menos que planee llamar a writeObject (null). La prueba para EOS con readObject () es catch (EOFException exc).


Así que construye BufferedOutputStream & flush it antes de construir BufferedInputStream. Para evitar colgar

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4788782

dice según la documentación

Si modifica el caso de prueba de manera que tanto el AServer como el AClient construyan el ObjectOutputStream antes que el ObjectInputStream, la prueba no se bloquea. Este es el comportamiento esperado dada la siguiente documentación:

Constructor ObjectOutputStream:
Crea un ObjectOutputStream que escribe en el especificado
Flujo de salida. Este constructor escribe el encabezado de la secuencia de serialización en la secuencia subyacente; las personas que llaman pueden desechar el flujo inmediatamente para asegurarse de que los constructores reciban
ObjectInputStreams no se bloqueará al leer el encabezado.

Constructor ObjectInputStream:
Crea un ObjectInputStream que lee del especificado
Flujo de entrada. Un encabezado de secuencia de serialización se lee de la secuencia y se verifica. Este constructor bloqueará hasta el correspondiente
ObjectOutputStream ha escrito y vació el encabezado.


Espero que tengas que llamar a objectOutputStream.flush() en ambos lados para asegurarte de que los datos se envíen inmediatamente a la red. De lo contrario, la pila TCP puede esperar un tiempo para que más datos llenen un paquete IP parcial.