ejemplos - Rendimiento de la creación de C++ std:: string desde un iterador de entrada
list iterator c++ (3)
¿Qué pasa con el rendimiento si intentas hacer eso? En lugar de preguntar "¿de qué manera es más rápido?" puedes pensar "oye, puedo medir esto".
Configure un bucle que lea un archivo de un tamaño determinado 10000 veces o algo así, y cítelo. Entonces hágalo con el método reserve()
y el tiempo que. Pruébelo con algunos tamaños de archivo diferentes (de pequeño a enorme) y vea lo que obtiene.
Estoy haciendo algo realmente simple: sorber un archivo de texto completo desde el disco a una std::string
. Mi código actual básicamente hace esto:
std::ifstream f(filename);
return std::string(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>());
Es muy poco probable que esto tenga algún tipo de impacto en el rendimiento del programa, pero todavía tengo curiosidad si esta es una forma lenta de hacerlo.
¿Existe el riesgo de que la construcción de la cadena implique muchas reasignaciones? ¿Sería mejor (es decir, más rápido) usar seekg()
/ tellg()
para calcular el tamaño del archivo y reserve()
ese espacio en la cadena antes de hacer la lectura?
Analicé su implementación (1), la mía (2) y otras dos (3 y 4) que encontré en .
Resultados (Promedio de 100 carreras; cronometrado con gettimeofday, el archivo tenía 40 párrafos de lorem ipsum):
- readFile1: 764
- readFile2: 104
- leerFile3: 129
- readFile4: 402
Las implementaciones:
string readFile1(const string &fileName)
{
ifstream f(fileName.c_str());
return string(std::istreambuf_iterator<char>(f),
std::istreambuf_iterator<char>());
}
string readFile2(const string &fileName)
{
ifstream ifs(fileName.c_str(), ios::in | ios::binary | ios::ate);
ifstream::pos_type fileSize = ifs.tellg();
ifs.seekg(0, ios::beg);
vector<char> bytes(fileSize);
ifs.read(&bytes[0], fileSize);
return string(&bytes[0], fileSize);
}
string readFile3(const string &fileName)
{
string data;
ifstream in(fileName.c_str());
getline(in, data, string::traits_type::to_char_type(
string::traits_type::eof()));
return data;
}
string readFile4(const std::string& filename)
{
ifstream file(filename.c_str(), ios::in | ios::binary | ios::ate);
string data;
data.reserve(file.tellg());
file.seekg(0, ios::beg);
data.append(istreambuf_iterator<char>(file.rdbuf()),
istreambuf_iterator<char>());
return data;
}
Para ser sincero, no estoy seguro, pero por lo que he leído, realmente depende de los iteradores. En el caso de los iteradores de secuencias de archivos, probablemente no tenga un método incorporado para medir la longitud del archivo entre el comienzo y el final.
Si esto es correcto, funcionará de forma similar a duplicar su tamaño de almacenamiento interno cada vez que se quede sin espacio. En este caso, para n caracteres en el archivo habrá Log [n, 2] asignaciones de memoria y eliminaciones de memoria, y n * Log [n, 2] copias de caracteres individuales, además de simplemente copiar los caracteres en la cadena.
Sin embargo, como Greg señaló, es mejor que lo pruebes. Como dijo, pruébelo para una variedad de tamaños de archivo para ambas técnicas. Además, puede usar lo siguiente para obtener algunos tiempos cuantitativos.
#include<time.h>
#include<iostream>
...
clock_t time1=0, time2=0, delta;
float seconds;
time1=clock();
//Put code to be timed here
time2=clock();
delta= time2-time1;
seconds =(((float)delta)/((float)CLOCKS_PER_SEC));
std::cout<<"The operation took: "<<seconds<<" seconds."<<std::endl;
...
esto debería hacer el truco para el tiempo.