¿Es std :: ifstream significativamente más lento que FILE?

Me han informado que mi biblioteca es más lenta de lo que debería ser, del orden de más de 30 veces demasiado lento para analizar un archivo en particular (archivo de texto, tamaño 326 kb). El usuario sugirió que es posible que esté usando std::ifstream (presumiblemente en lugar de FILE ).

Prefiero no reescribir a ciegas, así que pensé en verificar aquí primero, ya que supongo que el cuello de botella está en otra parte. Estoy leyendo carácter por carácter, por lo que las únicas funciones que uso son get() , peek() y tellg()/seekg() .

Actualizar:

Hice un perfil, y obtuve resultados confusos : gprof no pareció pensar que tomó tanto tiempo. Reescribí el progtwig para leer todo el archivo en un búfer primero y aceleró aproximadamente 100x. Creo que el problema pudo haber sido el tellg()/seekg() que demoró mucho tiempo, pero es posible que gprof no haya podido verlo por algún motivo. En cualquier caso, ifstream no parece almacenar en búfer todo el archivo, incluso para este tamaño.

No creo que eso haga la diferencia. Especialmente si estás leyendo char por char, es probable que la sobrecarga de E / S domine por completo cualquier otra cosa . ¿Por qué lees bytes individuales a la vez? ¿Sabes lo extremadamente ineficiente que es?

En un archivo de 326 kb, la solución más rápida será simplemente leerla en la memoria de una vez.

La diferencia entre std :: ifstream y los equivalentes C, es básicamente una llamada de función virtual o dos. Puede marcar la diferencia si se ejecuta algunas decenas de millones de veces por segundo, de lo contrario, no real. La E / S de archivo generalmente es tan lenta que la API utilizada para acceder a ella realmente no importa. Lo que importa mucho más es el patrón de lectura / escritura. Muchas búsquedas son malas, las lecturas / escrituras secuenciales son buenas.

Debería ser un poco más lento, pero al igual que lo que dijiste, podría no ser el cuello de botella. ¿Por qué no perfila su progtwig y ve si ese es el caso?

Creo que es poco probable que su problema se solucione al cambiar de fstream a FILE *, por lo general ambos son almacenados en la biblioteca C. También el sistema operativo puede leer en caché (Linux es muy bueno en ese aspecto). Dado el tamaño del archivo al que está accediendo, es bastante probable que esté completamente en la memoria RAM.

Al igual que PolyThinker, su mejor opción es ejecutar su progtwig a través de un generador de perfiles y determinar dónde está el problema.

También está utilizando seekg / tellg esto puede causar retrasos notables si su disco está muy fragmentado, porque para leer el archivo por primera vez, el disco tiene que mover los cabezales a la posición correcta.

Todos los puntos de referencia son malvados. Solo perfila tu código para los datos que esperas.

Realicé una comparación de rendimiento de E / S entre Ruby, Python, Perl, C ++ una vez. Para mis datos, versiones de idiomas, etc. La variante de C ++ fue varias veces más lenta (fue una gran sorpresa en ese momento).

Estoy de acuerdo en que deberías hacer un perfil. Pero si estás leyendo el archivo, un personaje a la vez, ¿qué tal crear un archivo mapeado en memoria? De esta forma, puede tratar el archivo como una matriz de caracteres, y el sistema operativo debe ocuparse de todo el almacenamiento en búfer de bajo nivel para usted. La solución más simple y probablemente más rápida es una victoria en mi libro. 🙂

Aquí hay un punto de referencia excelente que muestra que en condiciones extremas, los fstream s son realmente bastante lentos … a menos que:

  1. Usas buffering (no puedo enfatizar eso lo suficiente)
  2. Usted manipula el búfer usted mismo (es decir, si necesita un rendimiento como OP en la pregunta vinculada), que no es tan diferente de usar FILE* .

Sin embargo, no debes optimizar prematuramente. fstreams general, los fstreams son mejores, y si necesita optimizarlos en el camino, siempre puede hacerlo más tarde con un costo mínimo. Con el fin de prepararse para lo peor de antemano, sugiero crear un proxy mínimo para fstream ahora para que pueda optimizarlo más tarde, sin necesidad de tocar nada más.