He creado un perfil de algún código heredado que he heredado con cProfile. Hubo un montón de cambios que ya he hecho que me han ayudado (¡como usar las extensiones C de simplejson!).Aceleración de la escritura en los archivos
Básicamente este script 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 de a una por vez y toma un tiempo (5-10 filas por segundo).
Al generarse cada fila, se escribe en el disco lo más simple posible. El perfilado indica que aproximadamente 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 reducirá la cantidad de tiempo dedicado a 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 a la 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()
Lo primero que pensé fue 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 dentro.
¿Cuál es el cuello de botella de la aplicación? –
Pensé que era claro. Pasar el 20% de su tiempo escribiendo en el disco una fila a la vez. – chmullig
Bueno, haz el cambio y perfilalo? Se espera que tenga poco efecto, ya que la E/S de archivo suele estar almacenada en línea ... o eso supongo. – delnan