utiliza sirve que para libreria funcion dev cerr biblioteca c++ performance ostream istream

c++ - sirve - ¿Por qué es istream/ostream lento?



iostream h en c (4)

En realidad, ¡IOStreams no tiene que ser lento! Sin embargo, es una cuestión de implementarlos de una manera razonable para hacerlos rápidos. La mayoría de las bibliotecas estándar de C ++ no parecen prestar demasiada atención a la implementación de IOStreams. Hace mucho tiempo, cuando mi CXXRT aún se mantenía, era tan rápido como el stdio, ¡cuando se usaba correctamente!

Sin embargo, tenga en cuenta que existen pocas trampas de rendimiento para los usuarios distribuidos con IOStreams. Las siguientes pautas se aplican a todas las implementaciones de IOStream, pero especialmente a aquellas que están diseñadas para ser rápidas:

  1. Cuando use std::cin , std::cout , etc., debe llamar a std::sync_with_stdio(false) ! Sin esta llamada, cualquier uso de los objetos de flujo estándar es necesario para sincronizar con los flujos estándar de C. Por supuesto, cuando se usa std::sync_with_stdio(false) se asume que no mezcla std::cin con stdin , std::cout con stdout , etc.
  2. No use std::endl ya que exige muchos vaciados innecesarios de cualquier búfer. Del mismo modo, no establezca std::ios_base::unitbuf o use std::flush innecesariamente.
  3. Al crear sus propios búferes de flujo (OK, pocos usuarios lo hacen), ¡asegúrese de que utilicen un búfer interno! El procesamiento de caracteres individuales salta a través de múltiples condiciones y una función virtual que lo hace terriblemente lento.

A las 50:40 de http://channel9.msdn.com/Events/GoingNative/2013/Writing-Quick-Code-in-Cpp-Quickly Andrei Alexandrescu hace una broma acerca de qué tan eficiente / lento es el istream.

En el pasado tuve un problema con ostream que era lento y que la escritura era significativamente más rápida (reduciendo muchos segundos al ejecutar el bucle principal una vez) pero nunca entendí por qué ni lo examiné.

¿Qué hace que istream y ostream sean lentos en C ++? o al menos lento en comparación con otras cosas (como fread / fget, fwrite) que satisfarían igualmente las necesidades.


Quizás esto pueda dar una idea de con qué estás tratando:

#include <stdio.h> #include <iomanip> #include <iostream> #include <iterator> #include <fstream> #include <time.h> #include <string> #include <algorithm> unsigned count1(FILE *infile, char c) { int ch; unsigned count = 0; while (EOF != (ch=getc(infile))) if (ch == c) ++count; return count; } unsigned int count2(FILE *infile, char c) { static char buffer[8192]; int size; unsigned int count = 0; while (0 < (size = fread(buffer, 1, sizeof(buffer), infile))) for (int i=0; i<size; i++) if (buffer[i] == c) ++count; return count; } unsigned count3(std::istream &infile, char c) { return std::count(std::istreambuf_iterator<char>(infile), std::istreambuf_iterator<char>(), c); } unsigned count4(std::istream &infile, char c) { return std::count(std::istream_iterator<char>(infile), std::istream_iterator<char>(), c); } unsigned int count5(std::istream &infile, char c) { static char buffer[8192]; unsigned int count = 0; while (infile.read(buffer, sizeof(buffer))) count += std::count(buffer, buffer+infile.gcount(), c); count += std::count(buffer, buffer+infile.gcount(), c); return count; } unsigned count6(std::istream &infile, char c) { unsigned int count = 0; char ch; while (infile >> ch) if (ch == c) ++count; return count; } template <class F, class T> void timer(F f, T &t, std::string const &title) { unsigned count; clock_t start = clock(); count = f(t, ''N''); clock_t stop = clock(); std::cout << std::left << std::setw(30) << title << "/tCount: " << count; std::cout << "/tTime: " << double(stop-start)/CLOCKS_PER_SEC << "/n"; } int main() { char const *name = "equivs2.txt"; FILE *infile=fopen(name, "r"); timer(count1, infile, "ignore"); rewind(infile); timer(count1, infile, "using getc"); rewind(infile); timer(count2, infile, "using fread"); fclose(infile); std::ifstream in2(name); timer(count3, in2, "ignore"); in2.clear(); in2.seekg(0); timer(count3, in2, "using streambuf iterators"); in2.clear(); in2.seekg(0); timer(count4, in2, "using stream iterators"); in2.clear(); in2.seekg(0); timer(count5, in2, "using istream::read"); in2.clear(); in2.seekg(0); timer(count6, in2, "using operator>>"); return 0; }

Ejecutando esto, obtengo resultados como este (con MS VC ++):

ignore Count: 1300 Time: 0.309 using getc Count: 1300 Time: 0.308 using fread Count: 1300 Time: 0.028 ignore Count: 1300 Time: 0.091 using streambuf iterators Count: 1300 Time: 0.091 using stream iterators Count: 1300 Time: 0.613 using istream::read Count: 1300 Time: 0.028 using operator>> Count: 1300 Time: 0.619

y esto (con MinGW):

ignore Count: 1300 Time: 0.052 using getc Count: 1300 Time: 0.044 using fread Count: 1300 Time: 0.036 ignore Count: 1300 Time: 0.068 using streambuf iterators Count: 1300 Time: 0.068 using stream iterators Count: 1300 Time: 0.131 using istream::read Count: 1300 Time: 0.037 using operator>> Count: 1300 Time: 0.121

Como podemos ver en los resultados, no es realmente una cuestión de que los flujos de información sean categóricamente lentos. Más bien, mucho depende de cómo use iostreams (y, en menor medida, también de FILE * ). También hay una variación bastante sustancial solo entre estas y las implementaciones.

No obstante, las versiones más rápidas con cada ( fread y istream::read ) están esencialmente vinculadas. Con VC ++, getc es un poco más lento que istream::read o istreambuf_iterator .

Conclusión: obtener un buen rendimiento de iostreams requiere un poco más de cuidado que con FILE * , pero es ciertamente posible. También le brindan más opciones: conveniencia cuando no le importa mucho la velocidad y un rendimiento directamente competitivo con lo mejor que puede obtener de E / S de estilo C, con un poco de trabajo adicional.


Si bien esta pregunta es bastante antigua, me sorprende que nadie haya mencionado la construcción de objetos iostream.

Es decir, siempre que cree un iostream STL (y otras variantes de flujo), si ingresa en el código, el constructor llama a una función Init interna. Allí, se llama al operator new para crear un nuevo objeto de locale . Y asimismo, se destruye a la destrucción.

Esto es horrible, en mi humilde opinión. Y ciertamente contribuye a la lenta construcción / destrucción de objetos, porque la memoria se asigna / desasigna mediante un bloqueo del sistema, en algún momento.

Además, algunas de las secuencias de STL le permiten especificar un allocator , entonces, ¿por qué el locale creado NO usa el asignador especificado?

Al usar flujos en un entorno de multiproceso, también podría imaginar el cuello de botella impuesto por llamar al operator new cada vez que se construye un nuevo objeto de flujo.

Lío horrible si me preguntas, ¡como me estoy descubriendo ahora mismo!