2010-11-05 16 views
6

Escribo una aplicación cliente/servidor simple y descubrí que usar DataInputStream para leer datos era muy conveniente porque le permite elegir qué leer (sin tener que convertirlo usted mismo de bytes), pero me pregunto si sería mejor envolverlo en un BufferedInputStream también, o si eso solo agregaría una sobrecarga innecesaria?Java - ¿Cómo usar DataInputStream con Sockets, en búfer o no?

La razón por la que estoy preguntando es porque no sé qué tan caro es leer directamente de la secuencia de socket (al usar un BufferedInputStream, solo leerá una vez de la secuencia de socket y luego multiplicará las veces desde BufferedInputStream usando DataInputStream).

La información recibida suele ser bastante pequeña, alrededor de 20-25 Bytes.

¡Gracias de antemano por cualquier respuesta! : D

Respuesta

6

A DataInputStream no está tamponada, por lo que cada operación de lectura en un objeto DataInputStream va a resultar en una o más lee en la corriente de socket subyacente, y que podrían resultar en múltiples llamadas de sistema (o el equivalente) .

Una llamada al sistema suele ser de 2 a 3 órdenes de magnitud más costosa que una llamada a un método normal. Los flujos almacenados en búfer funcionan reduciendo el número de llamadas al sistema (idealmente a 1), a costa de agregar una capa adicional de llamadas a métodos regulares. Por lo general, el uso de una secuencia amortiguada reemplaza N syscalls con 1 syscall y N llamadas a métodos adicionales. Si N es mayor que 1, ganas.

De ello se deduce que los únicos casos en los que poner un BufferedInputStream entre la corriente de toma de corriente y el DataInputStream es no una victoria son:

  • cuando la aplicación sólo hace que uno read...() llamada y que puede ser satisfecha por una single syscall,
  • cuando la aplicación solo realiza llamadas grandes read(byte[] ...), o
  • cuando la aplicación no lee nada.

Parece que esto no se aplica en su caso.

Además, incluso si se aplican, la sobrecarga de usar un BufferedInputStream cuando no es necesario es relativamente pequeño. La sobrecarga de no usar un BufferedInputStream cuando lo necesites puede ser enorme.

Un último punto, la cantidad real de datos leídos (es decir, el tamaño de los mensajes) es bastante irrelevante al enigma del buffer frente al búfer. Lo que realmente importa es la forma en que se leen los datos; es decir, la secuencia de llamadas read...() que su aplicación hará.

2

La sabiduría general es que las lecturas individuales en la transmisión subyacente son muy lentas, por lo que el almacenamiento en memoria intermedia casi siempre es más rápido. Sin embargo, para números tan pequeños (20-25 bytes), puede ser que el costo de asignar el búfer sea similar al costo de hacer esas lecturas individuales (una vez que considera la asignación de memoria y la recolección de basura). Desafortunadamente, la única manera de descubrirlo es probarlo y ver.

Usted dice que los datos recibidos son generalmente small: ¿con qué frecuencia espera mensajes más grandes? Ese será un cuello de botella significativo si recibe ocasionalmente mensajes grandes en una transmisión sin búfer.

Le sugiero que realice algunas pruebas de tiempo y vea si el almacenamiento en memoria intermedia hace una diferencia en su caso. O bien, no se moleste con las pruebas de tiempo y simplemente use un buffer. Si el tamaño del mensaje cambia en el futuro, esto reducirá el mantenimiento más adelante.

+0

Eso no tiene sentido. El buffer se asigna una vez durante la vida útil del socket. Puede haber cualquier número de lecturas. Cuanto menor sea la lectura, más * significará * el almacenamiento en búfer. – EJP

+0

Si los clientes se conectan, enviar un pequeño mensaje, luego desconectarse (como lo haría algo de Ajax-y) y luego almacenar en búfer puede ser ineficiente. El número de lecturas debería ser bastante pequeño, pero quizás el rango de 20-25 sea lo suficientemente bajo. No lo sé: es por eso que sugerí hacer un perfil. –

+0

Ahora que lo pienso, AJAX no obtendrá mensajes de 20-25 bytes ... XML es demasiado detallado. Sin embargo, yo * he * asumido que los clientes no mantienen sus conexiones. Si esa suposición es incorrecta, siempre use un buffer. –

Cuestiones relacionadas