Pythonを使用してディスクから膨大な量のデータを処理する最も効率的な方法は何ですか?
-
12-10-2019 - |
質問
私は、他の方法で再構築することができなかった失敗したRAID5アレイからデータを読んで再構築するためのシンプルなPythonスクリプトを書いていました。私のスクリプトは実行されていますが、ゆっくりです。私の元のスクリプトは約80MB/minで実行されました。それ以来、私はスクリプトを改善し、550MB/minで実行されていますが、それでも少し低いようです。 Pythonスクリプトは100%CPUに座っているため、ディスク制限ではなくCPUのように見えます。つまり、最適化の機会があります。スクリプトはそれほど長くないので、私はそれを効果的にプロファイルすることができないので、何を食べているのかわかりません。これが今の私のスクリプトです(または少なくとも、重要なビット)
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]
この巨大なテキストブロック内の実際の質問を示すための太字:
これをより速く/より良いものにするために私ができることはありますか?何も思いもかかけない場合、これをゆっくりとしていることをよりよく研究するために私にできることはありますか? (1行あたりのレベルでPythonをプロファイルする方法もありますか?)これを正しい方法で処理することさえありますか、それとも膨大な量のバイナリデータを処理するより良い方法がありますか?
私が尋ねる理由は、3TBドライブの再構築があり、正しく動作しているにもかかわらず(画像RO、ループ、参照ファイルを正常にマウントできます)、長い時間がかかります。私はそれを1月中旬まで古いコードで服用していると測定しましたが、今ではクリスマスまでかかります(だからそれは 仕方 より良いですが、それは私が予想していたよりも遅いです。)
尋ねる前に、これはMDADM RAID5(64kbブロックサイズ、左対称)ですが、MDADMメタデータは何らかの形で欠落しており、MDADMはメタデータをディスクに書き直さずにRAID5を再構成することはできません。 、私は何かを台無しにしてデータを失う危険を冒したくありませんが、可能性は遠いかもしれません。
解決
Map(TakeXor、MagicPotato) - これはおそらく直接的な反復で行われる可能性があります。他のPythonコードAFAIKを呼び出す必要がある場合、マップは効率的ではありません。16384フレームオブジェクトを構築および破壊する必要があります。
structの代わりに配列モジュールを使用します
まだ遅すぎる場合は、Cythonでコンパイルして静的なタイプを追加します(おそらく2〜3桁速くなります)
他のヒント
Google for:WideFinder Python。 Pythonエントリで説明されている手法のいくつかは、IOをマッピングするメモリマッピングなど、使用する可能性があります。