reales - ¿Cuándo construir su propio sistema de almacenamiento intermedio para E/S(C++)?
introducción a android studio incluye proyectos reales y el código fuente pdf (7)
Tengo que lidiar con archivos de texto muy grandes (2 GB), es obligatorio leerlos / escribirlos línea por línea. Escribir 23 millones de líneas utilizando ofstream es muy lento, así que, al principio, traté de acelerar el proceso escribiendo grandes trozos de líneas en un búfer de memoria (por ejemplo, 256 MB o 512 MB) y luego escribí el búfer en el archivo . Esto no funcionó, el rendimiento es más o menos el mismo. Tengo el mismo problema al leer los archivos. Sé que las operaciones de E / S están protegidas por el sistema de E / S STL y esto también depende de la política del programador del disco (administrada por el sistema operativo, en mi caso, Linux).
¿Alguna idea sobre cómo mejorar el rendimiento?
PD: He estado pensando en utilizar un proceso hijo en segundo plano (o un hilo) para leer / escribir los fragmentos de datos mientras el programa está procesando datos, pero no sé (principalmente en el caso del subproceso) si esto valdrá la pena.
Si va a almacenar el archivo usted mismo, le aconsejo que realice algunas pruebas utilizando E / S sin búfer (setvbuf en un archivo que haya activado puede desactivar el almacenamiento en búfer de la biblioteca).
Básicamente, si va a protegerse usted mismo, quiere desactivar el almacenamiento en la memoria de la biblioteca, ya que solo le causará dolor. No sé si hay alguna forma de hacerlo para STL I / O, por lo que recomiendo bajar a la E / S de nivel C.
El uso de getline () puede ser ineficaz porque es posible que sea necesario volver a clasificar el tamaño del búfer de cadena varias veces a medida que se añaden datos desde el búfer de la secuencia. Puede hacer que esto sea más eficiente al cambiar el tamaño de la cadena:
También puede establecer el tamaño del búfer de iostreams a muy grande o NULL (para sin búfer)
// Unbuffered Accesses:
fstream file;
file.rdbuf()->pubsetbuf(NULL,0);
file.open("PLOP");
// Larger Buffer
std::vector<char> buffer(64 * 1024 * 1024);
fstream file;
file.rdbuf()->pubsetbuf(&buffer[0],buffer.size());
file.open("PLOP");
std::string line;
line.reserve(64 * 1024 * 1024);
while(getline(file,line))
{
// Do Stuff.
}
Solo un pensamiento, pero evite usar std :: endl ya que esto forzará una descarga antes de que el buffer esté lleno. Use ''/ n'' en su lugar para una nueva línea.
Tal vez deberías buscar en los archivos mapeados en la memoria.
Verifíquelos en esta biblioteca: Boost.Interprocess
También sugeriría archivos mapeados en memoria, pero si vas a usar boost creo que boost :: iostreams :: mapped_file es una mejor coincidencia que boost :: interprocess.
Un archivo de 2 GB es bastante grande, y debe conocer todas las áreas posibles que pueden actuar como cuellos de botella:
- El disco duro en sí
- La interfaz HDD (IDE / SATA / RAID / USB?)
- Sistema operativo / sistema de archivos
- Biblioteca C / C ++
- Tu codigo
Comenzaría haciendo algunas mediciones:
- ¿Cuánto tiempo tarda su código en leer / escribir un archivo de 2 GB?
¿Qué tan rápido puede leer y escribir el comando '' dd '' en el disco? Ejemplo...
dd if=/dev/zero bs=1024 count=2000000 of=file_2GB
- ¿Cuánto tiempo lleva escribir / leer usando solo grandes llamadas fwrite () / fread ()?
Suponiendo que su disco es capaz de leer / escribir a aproximadamente 40Mb / s (que es probablemente una cifra realista para comenzar), su archivo de 2GB no puede ejecutarse a más de 50 segundos.
¿Cuánto tiempo está tomando en realidad?
Hola, Roddy, usando el método de lectura fstream con archivos de 1.1 GB y grandes búferes (128,255 o 512 MB) toma alrededor de 43-48 segundos y es el mismo usando fstream getline (línea por línea). cp toma casi 2 minutos para copiar el archivo.
En ese caso, estás atado al hardware. cp tiene que leer y escribir, y buscará una y otra vez a través de la superficie del disco como loco cuando lo hace. Entonces, como verá, será más del doble de malo que el simple caso de "lectura".
Para mejorar la velocidad, lo primero que probaría es un disco duro más rápido o un SSD.
Usted no ha dicho lo que es la interfaz del disco? SATA es prácticamente la opción más fácil / rápida. Además (punto obvio, esto ...) asegúrate de que el disco esté físicamente en la misma máquina en la que se está ejecutando tu código, de lo contrario estarás vinculado a la red ...
No use nuevo para asignar el buffer así:
Pruebe: std :: vector <>
unsigned int buffer_size = 64 * 1024 * 1024; // 64 MB for instance.
std::vector<char> data_buffer(buffer_size);
_file->read(&data_buffer[0], buffer_size);
Lea también el artículo sobre el uso del subrayado en los nombres de los identificadores:. Tenga en cuenta que su código está bien, pero.