Quelle est la façon la plus efficace de traiter des quantités massives de données à partir d'un disque en utilisant python?

StackOverflow https://stackoverflow.com/questions/4507545

Question

Je rédigeais un script python simple pour lire et reconstruire les données d'un tableau RAID5 échoué que je suis incapable de reconstruire de toute autre manière. Mon script est en cours d'exécution, mais lentement. Mon RAN d'origine de script à environ 80 Mo / min. Je l'ai depuis amélioré le script et il est en cours d'exécution à 550 Mo / min mais qui semble encore un peu faible. Le script python est assis à 100% du CPU, il semble être CPU plutôt que disque limité, ce qui signifie que j'ai l'occasion d'optimisation. Parce que le script est pas très longtemps à tout ce que je suis incapable de le profil efficacement, donc je ne sais pas ce manger tout. Voici mon script tel qu'il est en ce moment (ou du moins, les bits importants)

disk0chunk = disk0.read(chunkSize)
#disk1 is missing, bad firmware
disk2chunk = disk2.read(chunkSize)
disk3chunk = disk3.read(chunkSize)
if (parityDisk % 4 == 1): #if the parity stripe is on the missing drive
  output.write(disk0chunk + disk2chunk + disk3chunk)
else: #we need to rebuild the data in disk1
  # disk0num = map(ord, disk0chunk) #inefficient, old code
  # disk2num = map(ord, disk2chunk) #inefficient, old code
  # disk3num = map(ord, disk3chunk) #inefficient, old code
  disk0num = struct.depack("16384l", disk0chunk) #more efficient new code
  disk2num = struct.depack("16384l", disk2chunk) #more efficient new code
  disk3num = struct.depack("16384l", disk3chunk) #more efficient new code
  magicpotato = zip(disk0num,disk2num,disk3num)
  disk1num = map(takexor, magicpotato)
  # disk1bytes = map(chr, disk1num) #inefficient, old code
  # disk1chunk = ''.join(disk1bytes) #inefficient, old code
  disk1chunk = struct.pack("16384l", *disk1num) #more efficient new code

  #output nonparity to based on parityDisk

def takexor(magicpotato):
  return magicpotato[0]^magicpotato[1]^magicpotato[2]

Bolding pour indiquer les questions réelles à l'intérieur de ce bloc géant du texte:

Est-ce que je peux être en train de faire pour rendre ce plus vite / mieux? Si rien ne vient à l'esprit, est-ce que je peux faire pour améliorer la recherche sur ce qui fait passer ça lentement? (Y at-il même un moyen de profil à un python par niveau ligne?) Suis-je manipuler même ce la bonne voie, ou est-il une meilleure façon de gérer des quantités massives de données binaires?

La raison pour laquelle je demande est que j'ai un lecteur de 3To reconstruire et même si le fonctionnement est correct (je peux monter l'image ro, boucle et fichiers parcourir fin), il prend beaucoup de temps. Je l'ai mesuré en prenant jusqu'à la mi-Janvier avec l'ancien code, maintenant il va prendre jusqu'à Noël (il est donc chemin mieux, mais il est encore plus lent que prévu qu'il soit.)

Avant de vous demander, c'est un mdadm RAID5 (64kb blocksize, symétrique à gauche), mais les métadonnées de mdadm manque en quelque sorte et mdadm ne vous permet pas de configurer de nouveau un RAID5 sans réécrire les métadonnées sur le disque, que je suis en train d'éviter à tout prix, je ne peut cependant la possibilité à distance voulez pas risquer de visser quelque chose et de perdre des données, être.

Était-ce utile?

La solution

  1. carte (takexor, magicpotato) - Ceci est probablement mieux fait avec itération directe, la carte n'est pas efficace si elle a besoin d'appeler un autre code python AFAIK, il a besoin de construire et détruire cadre 16384 objets pour effectuer l'appel , etc.

  2. Utiliser le module de réseau à la place du struct

  3. S'il est encore trop lent compiler avec cython et ajouter certains types de statiques (qui va probablement faire 2-3 ordres de grandeur plus rapide)

Autres conseils

Google pour: python widefinder. Certaines des techniques décrites dans les entrées Python pourraient être utiles, telles que la cartographie de la mémoire IO.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top