2009-08-28 12 views
11

Necesitamos leer y contar diferentes tipos de mensajes/ejecutar algunas estadísticas en un archivo de texto de 10 GB, por ejemplo, un FIX motor log. Usamos Linux, 32 bits, 4 CPUs, Intel, codificación en Perl pero , el lenguaje en realidad no importa.¿Cuál es la manera más rápida de leer un archivo de 10 GB del disco?

He encontrado algunos consejos interesantes en Tim Bray's WideFinder project. Sin embargo, hemos encontrado que el uso de la asignación de memoria está intrínsecamente limitado por la arquitectura de 32 bits.

Intentamos usar procesos múltiples, lo que parece funcionar más rápido si procesamos el archivo en paralelo usando 4 procesos en 4 CPUs. Agregar múltiples subprocesos lo ralentiza, tal vez debido al costo del cambio de contexto. Intentamos cambiar el tamaño del grupo de subprocesos, pero aún es más lento que versión multiproceso simple.

La parte de asignación de memoria no es muy estable, a veces toma 80 segundos y, a veces 7 segundos en un archivo de 2 GB, tal vez de errores de página o algo relacionado con el uso de la memoria virtual. De todos modos, Mmap no puede escalar más allá de 4 GB en una arquitectura de 32 bit .

Probamos Perl's IPC::Mmap y Sys::Mmap. Miró en Map-Reduce también, pero el problema es realmente E/S obligado, el procesamiento en sí es lo suficientemente rápido.

así que decidimos tratar de optimizar la E/S básica sintonizando tamaño de búfer, tipo, etc.

Puede cualquier persona que tenga conocimiento de un proyecto existente en este problema fue resuelto de manera eficiente en cualquier lenguaje/plataforma apuntan a un enlace útil o sugieren una dirección?

+2

¿Cuál es el rendimiento bruto en una sola CPU para 2G? Probablemente necesite determinar si la E/S es el problema o los cálculos de la CPU. – Cervo

+2

Si realmente está vinculado al disco (IO), entonces la mejor opción es comprar discos más rápidos, más discos (en RAID0, RAID5, RAID10, etc.) o una máquina de 64 bits con memoria suficiente para almacenar el archivo en un disco RAM Cualquier disco único razonable debería ser capaz de extraer 50MB/seg; múltiples discos rápidos deberían poder empujarlo a por lo menos 300MB/seg. – derobert

+1

Te recomiendo que no uses Sys :: Mmap sino File-Map (por los motivos que se indican en la documentación de este último). En cualquier caso, probablemente no desee usar IPC :: Mmap. –

Respuesta

9

La mayoría de las veces estará obligado a E/S no vinculado a la CPU, por lo tanto, simplemente lea este archivo a través de la Perl I/O normal y trátelo en un solo hilo. A menos que demuestre que puede hacer más E/S que su CPU sola, no pierda el tiempo con nada más. De todos modos, deberías preguntar: ¿Por qué en la Tierra está esto en un gran archivo? ¿Por qué en la Tierra no lo dividen de manera razonable cuando lo generan? Sería una gran cantidad de trabajo que vale la pena. Luego puede colocarlo en canales de E/S separados y usar más CPU (si no usa algún tipo de RAID 0 o NAS o ...).

Mida, no asuma. No olvide lavar los cachés antes de cada prueba. Recuerde que las E/S en serie tienen una magnitud más rápida que aleatoria.

0

Me parece recordar un proyecto en el que estábamos leyendo archivos grandes. Nuestra implementación utilizaba multiprocesamiento: básicamente, n * working_threads comenzaba a incrementar las compensaciones del archivo (0, chunk_size, 2xchunk_size, 3x chunk_size ... n-1x chunk_size) y estaba leyendo fragmentos de información más pequeños. No puedo recordar exactamente nuestro razonamiento para esto, ya que alguien más lo estaba diseñando todo: los trabajadores no fueron lo único que hicieron, pero así es como lo hicimos.

creo que sirve

2

ha pensado en el streaming el archivo y filtrando a un archivo secundario ningún resultado interesantes? (Repita hasta que tenga un archivo de tamaño manejable).

3

Tal vez usted ha leído ya este hilo del foro, pero si no:

http://www.perlmonks.org/?node_id=512221

En él se describe el uso de Perl para hacerlo, línea por línea, y los usuarios parecen pensar Perl es muy capaz de eso

¿Es posible procesar el archivo desde una matriz RAID? Si tiene varios discos duplicados, la velocidad de lectura se puede mejorar. La competencia por los recursos de disco puede ser lo que hace que su intento de múltiples hilos no funcione.

Lo mejor de la suerte.

3

Desearía saber más sobre el contenido de su archivo, pero sin saber que es texto, esto parece un excelente problema de MapReduce.

PS, la lectura más rápida de cualquier archivo es una lectura lineal. cat file > /dev/null debe ser la velocidad con la que se puede leer el archivo.

+3

De hecho; Mi colega que trabajaba en un problema similar estaba usando el tiempo de cat para rastrear otros problemas en las velocidades de lectura de archivos. NFS fue una horrible mierda de tiempo. :( –

1

Básicamente necesita "Dividir y conquistar", si tiene una red de computadoras, luego copie el archivo 10G en tantas PC cliente como sea posible, haga que cada PC cliente lea un desplazamiento del archivo. Para una ventaja adicional, obtenga CADA PC para implementar múltiples subprocesos además de la lectura distribuida.

+3

"el problema es realmente IO obligado" <--- buena suerte copiando el archivo a una máquina más rápido que los discos pueden leerlo. – derobert

1

Analice el archivo una vez, leyendo línea por línea. Pon los resultados en una tabla en una base de datos decente. Ejecuta tantas consultas como desees. Alimenta a la bestia regularmente con nuevos datos entrantes.

Tenga en cuenta que manipular un archivo de 10 Gb, transferirlo a través de la red (incluso si es local), explorar soluciones complicadas, etc. todo lleva su tiempo.

+2

La base de datos de fuentes y las consultas de ejecución pueden tomar más tiempo que todo el proceso en perl. Es a partir de la experiencia de la mina, incluso si usas carga masiva y MySQL, que es uno de los enfoques más rápidos que puedes usar.) –

+1

Una vez que tenga los datos en una base de datos * decente, puede ejecutar tantas consultas como desee (incluso aquellas que no sabía que podría haber deseado ejecutar) con un pequeño costo adicional. –

1

Tengo un compañero de trabajo que aceleró su lectura de FIX yendo a Linux de 64 bits. Si es algo que vale la pena, deje un poco de dinero en efectivo para obtener hardware más elegante.

4

Todo esto depende de qué tipo de preprocesamiento puede hacer y cuándo. En algunos de los sistemas que tenemos, descomprimimos esos archivos de texto de gran tamaño, reduciéndolos a 1/5 a 1/7 de su tamaño original. Parte de lo que hace esto posible es que no necesitamos procesar estos archivos hasta horas después de su creación, y en el momento de la creación no tenemos otra carga en las máquinas.

Procesándolas se hace más o menos a la manera de esos archivos zcat | ourprocessing. (bueno, está hecho sobre sockets Unix, aunque con un zcat hecho a medida). Cambia el tiempo de CPU para el tiempo de E/S de disco, y para nuestro sistema que ha sido y vale la pena. Por supuesto, hay muchas variables que pueden hacer que este sea un diseño muy pobre para un sistema en particular.

1

hmmm, pero ¿qué hay de malo con el comando read() en C? Por lo general, tiene un límite de 2 GB, , así que simplemente llámalo 5 veces en secuencia. Eso debería ser bastante rápido.

1

Si está vinculado a E/S y su archivo está en un único disco, entonces no hay mucho que hacer. Un simple escaneo lineal de un solo hilo en todo el archivo es la manera más rápida de obtener los datos del disco. Usar tamaños de búfer grandes podría ayudar un poco.

Si puede convencer al escritor del archivo para que lo recorra en varios discos/máquinas, entonces podría pensar en el multihilo del lector (un hilo por cabezal de lectura, cada hilo leyendo los datos de una sola banda).

0

No se especifica en el problema que la secuencia realmente importa o no.Por lo tanto, divida el archivo en partes iguales, digamos 1GB cada una, y dado que está usando múltiples CPU, entonces no será un problema con múltiples hilos, así que lea cada archivo usando un hilo separado y use RAM de capacidad> 10 GB, luego todos sus contenidos se almacenaría en la RAM leída por múltiples hilos.

1

Dado que dicha plataforma y el idioma no importa ...

Si desea un rendimiento estable que es tan rápido como el medio fuente permite, la única manera que soy consciente de que esto se puede hacer en Windows se realiza mediante lecturas secuenciales alineadas y no almacenadas en el SO. Es probable que pueda acceder a algunos GB/s con dos o tres búferes, más allá de eso, en algún momento necesita un búfer en anillo (un escritor, lectores 1+) para evitar cualquier copia. La implementación exacta depende del controlador/API. Si hay una copia de memoria en el hilo (tanto en el kernel como en el modo de usuario) relacionado con el IO, obviamente el buffer más grande es para copiar, cuanto más tiempo se desperdicia en eso en lugar de hacer el IO. Entonces, el tamaño de búfer óptimo depende del firmware y el controlador. En Windows, los buenos valores para intentar son múltiplos de 32 KB para el disco IO. El búfer de archivos de Windows, la asignación de memoria y todo eso agrega sobrecarga. Solo es bueno si se realizan (o ambas) lecturas múltiples de los mismos datos en forma de acceso aleatorio. Por lo tanto, para leer un archivo grande secuencialmente una sola vez, no desea que el SO almacene nada o haga cualquier memcpy. Si usa C#, también hay penalizaciones por llamar al sistema operativo debido a la clasificación, por lo que el código de interoperabilidad puede necesitar un poco de optimización a menos que use C++/CLI.

Algunas personas prefieren lanzar hardware a problemas pero si tiene más tiempo que dinero, en algunos casos es posible optimizar las cosas para realizar 100-1000x mejor en una sola computadora de nivel de consumidor que en 1000 computadoras con precios empresariales. La razón es que si el procesamiento también es sensible a la latencia, ir más allá del uso de dos núcleos probablemente esté agregando latencia. Esta es la razón por la que los conductores pueden empujar gigabytes/s, mientras que el software empresarial se queda bloqueado en megabytes/s en el momento en que todo está hecho. Cualquiera que sea el informe, la lógica empresarial y tal software empresarial probablemente también se pueda hacer en gigabytes/s en dos CPU centrales de consumo, si se escribe como si estuvieras en los 80 escribiendo un juego. El ejemplo más famoso que he escuchado acerca de abordar su lógica de negocio entera de esta manera es el intercambio de divisas LMAX, que publicó parte de su código basado en búfer de anillo, que se dice que está inspirado en los controladores de tarjetas de red.

Olvidando toda la teoría, si está contento con < 1 GB/s, un posible punto de partida en Windows que he encontrado es buscar fuente readfile de winimage, a menos que desee profundizar en muestras de sdk/controlador. Es posible que necesite algunas correcciones de código fuente para calcular el rendimiento correctamente a velocidades SSD. Experimente con tamaños de búfer también. Los switches/h multiproceso y/o superpuesto (puerto de terminación) IO con tamaño de búfer óptimo (intente 32,64,128 KB etc.) sin búfer de archivo de Windows en mi experiencia da mejor rendimiento cuando se lee desde SSD (datos fríos) mientras simultáneamente procesamiento (use/a para el procesamiento de Adler ya que de lo contrario está demasiado vinculado a la CPU).

Cuestiones relacionadas