2009-05-31 21 views
6

¿Cuál es la diferencia, en cuanto al rendimiento, entre leer desde un socket 1 byte un tiempo frente a leer en gran cantidad?Lectura de un socket 1 byte un tiempo frente a lectura en un fragmento grande

Tengo una aplicación C++ que necesita extraer páginas de un servidor web y analizar la página recibida línea por línea. Actualmente, estoy leyendo 1 byte a la vez hasta que encuentro un CRLF o se alcanza el máximo de 1024 bytes.

Si leer en gran cantidad (por ejemplo, 1024 bytes a la vez) es mucho mejor en cuanto a rendimiento, cualquier idea sobre cómo lograr el mismo comportamiento que tengo actualmente (es decir, poder almacenar y procesar 1 línea html en tiempo - hasta el CRLF sin consumir los bytes sucesivos todavía)?

EDIT:

no puedo pagar demasiado grandes memorias intermedias. Tengo un presupuesto de código muy ajustado ya que la aplicación se usa en un dispositivo integrado. Prefiero mantener solo un buffer de tamaño fijo, preferiblemente mantener una línea html a la vez. Esto hace que mi análisis sintáctico y otros procesos sean fáciles, ya que cada vez que intento acceder al búfer para analizarlos, puedo suponer que estoy procesando una línea html completa.

Gracias.

+0

¿Podría dar más detalles sobre el dispositivo embebido? ¿Tiene incluso un sistema operativo? –

Respuesta

4

Si está leyendo directamente de la toma, y ​​no de una representación de alto nivel intermedio que puede ser amortiguada, entonces, sin ninguna duda posible, es mejor leer completamente los 1024 bytes, ponerlos en RAM en un búfer y luego analizar los datos de la RAM.

¿Por qué? Leer en un socket es una llamada al sistema y causa un cambio de contexto en cada lectura, lo cual es costoso. Obtenga más información al respecto: IBM Tech Lib: Boost socket performances

+0

+1 - Me gusta su argumento sobre por qué la lectura en gran cantidad es mejor en cuanto a rendimiento. Creo que puedo conformarme con la respuesta de Neil Butterworth para resolver mi segunda preocupación. =) –

1

primera y más simple:

cin.getline(buffer,1024); 

En segundo lugar, por lo general todo IO es amortiguada por lo que no tiene que preocuparse demasiado inicia tercer lugar, proceso CGI

por lo general cuesta mucho más que el procesamiento de entrada (a menos es un gran archivo ) ... Así que simplemente no lo pienses más.

1

día G,

Uno de los grandes éxitos de rendimiento haciendo que un byte a la vez es que su contexto va de vez usuario a la hora del sistema y otra vez. Y más. No es eficiente en absoluto.

Asir un trozo grande, típicamente hasta un tamaño de MTU, es considerablemente más eficiente.

¿Por qué no escanea el contenido en un vector y repite eso buscando \ n para separar su entrada en líneas de entrada web?

HTH

aplausos,

+0

Sí, dependiendo del número de llamadas, la sobrecarga relativa causada por las llamadas a funciones puede llegar a ser significativa en algún momento. – none

5

que no puedo comentar en C++, pero desde otras plataformas - Sí, esto puede hacer una gran diferencia ; particularmente en la cantidad de interruptores que el código necesita hacer, y la cantidad de veces que necesita preocuparse por la naturaleza asincrónica de las corrientes, etc.

Pero la verdadera prueba es, por supuesto, darle un perfil. ¿Por qué no escribir una aplicación básica que revuelve un archivo arbitrario utilizando ambos enfoques, y probarlo para algunos archivos típicos ... el efecto suele ser sorprendente, si el código está vinculado a IO. Si los archivos son pequeños y la mayor parte del tiempo de ejecución de la aplicación se procesa los datos una vez que están en la memoria, es probable que no note ninguna diferencia.

1

No está leyendo un byte a la vez desde un socket, está leyendo un byte en un atime desde el sistema de E/S C/C++, que si está utilizando CGI tendrá todo el buffer de toda la información de la toma.El objetivo de la E/S almacenada en búfer es hacer que los datos estén disponibles para el programador de una manera que sea conveniente para ellos procesar, por lo que si desea procesar un byte a la vez, continúe.

Edit: Reflexionando, no queda claro si está implementando CGI o solo lo está usando. Puede aclarar esto publicando un fragmento de código que indique cómo lee actualmente ese byte único.

Si está leyendo directamente el zócalo, simplemente debe leer toda la respuesta al GET en un búfer y luego procesarlo. Esto tiene numerosas ventajas, incluido el rendimiento y la facilidad de codificación.

Si está linitted a un pequeño búfer, a continuación, utilizar algoritmos tampón clásicos como:

getbyte: 
    if buffer is empty 
     fill buffer 
     set buffer pointer to start of buffer 
    end 
    get byte at buffer pointer 
    increment pointer 
+0

No. Estoy leyendo desde un socket. Estoy haciendo la solicitud HTTP GET al servidor web y leo la respuesta de un socket. Lo hago porque necesito el contenido dinámico procesado y procesado por completo. –

+0

Creo que podría resolver con este algoritmo con una pequeña modificación. Puedo tener dos buffer de tamaño fijo. Uno para leer un entero (digamos 512 bytes), escanearlo y almacenar una única línea html completa en otro búfer al que podría acceder fácilmente en mis otros métodos de análisis sintáctico. Podría tener una rutina de lectura de socket más eficiente y podría mantener la facilidad de procesamiento que tengo ahora (es decir, mis otros métodos suponiendo una línea html completa). Gracias. =) –

0

No hay diferencia en el nivel del sistema operativo, los datos se almacenan de todos modos. Sin embargo, su aplicación debe ejecutar más código para "leer" bytes de a uno por vez.

1

Puede abrir el archivo de socket descritpor con la función fdopen(). Luego tiene IO protegido para que pueda llamar a fgets() o similar en ese descriptor.

+0

-1 para sugerir get(). – bk1e

+0

lo siento, quise decir que fgets(), editó mi respuesta ahora :-( – codymanix

+0

¡¿Cómo pudiste! – LukeN

Cuestiones relacionadas