4

これが私が完了する必要があるタスクのリストです:

  1. ファイルのチャンクを読み取る(ディスクIOバウンド)
  2. 上記のチャンクを暗号化する(CPUバウンド)
  3. 上記のチャンクをアップロード(ネットワークIOバウンド)
  4. ファイルがアップロードされるまで繰り返します

問題は、これを最大の効率とパフォーマンスで実現する方法にあります。

操作ブロック全体をカプセル化するために使用しようとしましParallel.Forたが、各操作には説明できるさまざまな特性があることを考えると、これがこの問題に取り組むための最良の方法ではないと思います(上記のリストで指摘したように) 。

この質問で提案されたこのTPLの記事を読み、その質問の経験的データを確認した後、TPLは私が行きたい方法だと思います。しかし、最大の効率とパフォーマンスを得るために、これをどのように分割する必要がありますか?アップロードが操作全体のボトルネックになる可能性があることを考慮して、最初の2つの操作をマルチスレッド化することをわざわざ行う必要がありますか?

ご入力いただきありがとうございます。

編集:

TasksとContinueWithを使用してOSに対処させようとしましたが、別の壁にぶつかっていると思います。すべてのアップロードタスクが完了するのを待つと、ガベージコレクターがクリーンアップされていないようです。アップロードするために読み込んだデータが原因で、メモリが不足してしまいます。考慮すべきさらに別の限界。

4

1 に答える 1

1

.Net 4.5 を使用できない場合は、ディスクからの読み取りに 1 つのスレッド、暗号化に 1 つのスレッド、アップロードに 1 つのスレッドを使用することをお勧めします。BlockingCollection<byte[]>それらの間で通信するには、スレッドの各ペア (1-2 と 2-3)の間の形式でプロデューサー/コンシューマー パターンを使用します。

しかし、.Net 4.5 を使用できるため、このタスクに最適な TPL Dataflow を使用できます。TPL Dataflow を使用すると、読み取りとアップロードのためにスレッドを浪費することがなくなります (ただし、ほとんど問題にはなりません)。さらに重要なことは、各チャンクの暗号化を簡単に並列化できることです (それができると仮定します)。

暗号化用に 1 つのブロック、アップロード用に 1 つのブロック、ファイルからの読み取り用に 1 つの非同期タスク (実際には、完全である必要はありませんTask) を用意します。暗号化のブロックは並行して実行するように構成でき、両方のブロックをある程度の最大容量で構成する必要があります (そうしないと、スロットリングが正しく機能せず、ファイル全体が可能な限り高速に読み取られ、OutOfMemoryException が発生する可能性があります)。

コード内:

var uploadBlock = new ActionBlock<byte[]>(
    data => uploadStream.WriteAsync(data, 0, data.Length),
    new ExecutionDataflowBlockOptions { BoundedCapacity = capacity });

var encryptBlock = new TransformBlock<byte[], byte[]>(
    data => Encrypt(data),
    new ExecutionDataflowBlockOptions
    {
        BoundedCapacity = capacity,
        MaxDegreeOfParallelism = degreeOfParallelism
    });

encryptBlock.LinkTo(
    uploadBlock,
    new DataflowLinkOptions { PropagateCompletion = true });

while (true)
{
    byte[] chunk = new byte[chunkSize];
    int read = await fileStream.ReadAsync(chunk, 0, chunk.Length);
    if (read == 0)
        break;
    await encryptBlock.SendAsync(chunk);
}

fileStream.Close();
encryptBlock.Complete();
await uploadBlock.Completion;
uploadStream.Close();
于 2012-12-22T14:09:18.590 に答える