Acelera la escritura en archivos

He perfilado algunos códigos heredados que he heredado con cProfile. Ya he hecho un montón de cambios que me han ayudado (como usar las extensiones C de simplejson).

Básicamente, esta secuencia de comandos está exportando datos de un sistema a un archivo de ancho fijo ASCII. Cada fila es un registro y tiene muchos valores. Cada línea tiene 7158 caracteres y contiene una tonelada de espacios. El recuento total de registros es de 1,5 millones de registros. Cada fila se genera una a la vez, y toma un tiempo (5-10 filas por segundo).

A medida que se genera cada fila, se escribe en el disco de la forma más sencilla posible. El perfil indica que alrededor del 19-20% del tiempo total se gasta en file.write() . Para un caso de prueba de 1,500 filas eso es 20 segundos. Me gustaría reducir ese número.

Ahora parece que la próxima victoria será reducir la cantidad de tiempo empleado en escribir en el disco. Me gustaría reducirlo, si es posible. Puedo mantener un caché de registros en la memoria, pero no puedo esperar hasta el final y volcarlo todo de una vez.

 fd = open(data_file, 'w') for c, (recordid, values) in enumerate(generatevalues()): row = prep_row(recordid, values) fd.write(row) if c % 117 == 0: if limit > 0 and c >= limit: break sys.stdout.write('\r%s @ %s' % (str(c + 1).rjust(7), datetime.now())) sys.stdout.flush() 

Mi primer pensamiento sería mantener un caché de registros en una lista y escribirlos en lotes. ¿Sería eso más rápido? Algo como:

 rows = [] for c, (recordid, values) in enumerate(generatevalues()): rows.append(prep_row(recordid, values)) if c % 117 == 0: fd.write('\n'.join(rows)) rows = [] 

Mi segundo pensamiento sería usar otro hilo, pero eso me da ganas de morir por dentro.

En realidad, su problema no es que file.write() tome el 20% de su tiempo. ¡Es que el 80% del tiempo no estás en file.write() !

Escribir en el disco es lento. Realmente no hay nada que puedas hacer al respecto. Simplemente toma mucho tiempo escribir las cosas en el disco. No hay casi nada que puedas hacer para acelerarlo.

Lo que desea es que el tiempo de E / S sea la parte más importante del progtwig, de modo que su velocidad esté limitada por la velocidad del disco duro y no por el tiempo de procesamiento. ¡Lo ideal es que file.write() tenga un uso del 100%!

Al agrupar las escrituras en grupos de 500 se aceleraron las escrituras significativamente. Para este caso de prueba, las filas de escritura tomaron individualmente 21.051 segundos en E / S, mientras que la escritura en lotes de 117 tomó 5.685 segundos para escribir el mismo número de filas. Los lotes de 500 tomaron un total de solo 0.266 segundos.

Puedes hacer mmap en python, lo que podría ayudar. Pero sospecho que cometió algún error al perfilar, porque 7k * 1500 en 20 segundos es de aproximadamente 0.5 Mbytes / s. Haz una prueba en la que escribas líneas aleatorias con la misma longitud, y verás que es mucho más rápido que eso.