Accélérer l'écriture de fichiers

J'ai profilé certains legacy code que j'ai hérité avec cProfile. Il y avait un tas de modifications, j'ai déjà qui l'ont aidé (comme l'utilisation de simplejson C extensions!).

Fondamentalement, ce script est de l'exportation des données d'un système vers un fichier ASCII à largeur fixe de fichier. Chaque ligne est un enregistrement, et il a beaucoup de valeurs. Chaque ligne est 7158 caractères et contient une tonne d'espaces. Au total, le nombre d'enregistrement est de 1,5 millions d'enregistrements. Chaque ligne est généré à la fois, et prend un certain temps (5 à 10 lignes par seconde).

Que chaque ligne est généré, il est écrit sur le disque le plus simplement possible. Le profilage indique qu'environ 19-20% du temps total passé dans file.write(). Pour un cas de test de 1 500 lignes que de 20 secondes. J'aimerais diminuer le nombre.

Maintenant, il semble que la prochaine victoire sera de réduire la quantité de temps passé à l'écriture sur le disque. Je tiens à le réduire, si possible. Je peux garder un cache d'enregistrements dans la mémoire, mais je ne peux pas attendre jusqu'à la fin et de vidage de tous à la fois.

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()

Ma première pensée serait de garder un cache d'enregistrements dans une liste et de les écrire dans les lots. Serait-ce plus rapide? Quelque chose comme:

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

Ma deuxième pensée serait d'utiliser un autre thread, mais qui me donne envie de mourir à l'intérieur.

  • Quel est le goulot d'étranglement de la demande?
  • Je croyais avoir été clair. Elle y consacre 20% de son temps à écrire sur le disque, une rangée à la fois.
  • Ainsi, faire le changement et le profil il? C'est s'attendre à avoir peu d'effet, comme e/S de fichier est généralement en ligne de tampon... ou alors je l'assume.
  • Le filetage ne va pas aider. Pourquoi êtes-vous rinçage tellement. Je veux dire, je sais que LeBron James "n'oublie jamais de chasse d'eau", mais avez-vous besoin de le faire à chaque fois que vous écrivez sur la sortie standard?
  • le rinçage est pour sa sortie standard (stdout), pas le fichier en question.
  • est droit. Je tire la chasse, juste pour le stdout de l'impression des rapports de situation. Cela n'arrive que tous les 117 lignes, ou environ une fois toutes les 20 secondes.
  • Ce cas de test à partir de votre code: pastebin.com/pyC8puAZ, s'exécute en moins d'une seconde. Quelle que soit la cause de la lenteur, sa cause pas par ce que vous avez posté.

InformationsquelleAutor chmullig | 2011-02-10