2009-08-17 14 views
5

私はロードバランスサーバからファイルをルーチンダウンロードするWindowsアプリケーションを作成しましたが、現在の速度は約30MB /秒です。しかし、FastCopyやTeraCopyを使用しようとすると、約100MB /秒でコピーできます。コピー速度を向上させて、現在よりも高速にファイルをコピーできるようにする方法を知りたい。私のアプリケーションコピーファイルをより速く作る方法

答えて

4

ストリームを使用する際のよくある間違いの1つは、一度に1バイトずつコピーするか、小さなバッファを使用することです。ディスクにデータを書き込むために必要な時間はほとんどがシークされるので、より大きなバッファを使用するとバイトあたりの平均シーク時間が短縮されます。

オペレーティングシステムはファイルをディスクにディスクに書き込みます。つまり、ディスクに1バイトを書き込むと、実際には512バイトと64 KBの間にブロックが書き込まれます。 64kbの整数倍のバッファを使用すると、ディスクのパフォーマンスを大幅に向上させることができます。

さらに、メモリページサイズの基礎となるCPUの倍数であるバッファを使用することで、ブーストを得ることができます。 x86/x64マシンの場合、これは4kbまたは4mbのいずれかに設定できます。

したがって、4mbの整数倍を使用します。

さらに、非同期IOを使用する場合は、大きなバッファサイズを十分に活用できます。

class Downloader 
{ 
    const int size = 4096 * 1024; 
    ManualResetEvent done = new ManualResetEvent(false); 
    Socket socket; 
    Stream stream; 

    void InternalWrite(IAsyncResult ar) 
    { 
     var read = socket.EndReceive(ar); 
     if (read == size) 
      InternalRead(); 
     stream.Write((byte[])ar.AsyncState, 0, read); 
     if (read != size) 
      done.Set(); 
    } 

    void InternalRead() 
    { 
     var buffer = new byte[size]; 
     socket.BeginReceive(buffer, 0, size, System.Net.Sockets.SocketFlags.None, InternalWrite, buffer); 
    } 

    public bool Save(Socket socket, Stream stream) 
    { 
     this.socket = socket; 
     this.stream = stream; 

     InternalRead(); 
     return done.WaitOne(); 
    } 
} 

bool Save(System.Net.Sockets.Socket socket, string filename) 
{ 
    using (var stream = File.OpenWrite(filename)) 
    { 
     var downloader = new Downloader(); 
     return downloader.Save(socket, stream); 
    } 
} 
2

おそらく、あなたのアプリケーションが複数のスレッドを使用してファイルを取得するには、マルチスレッド化を行うことができます、しかし、帯域幅がコンテンツを転送するデバイスの速度に制限されている

1

最も簡単な方法は、生/バイナリでファイルを開くことですモード(thats CはC#と同等のものであるかどうかはっきりしません)、一度に非常に大きなブロック(数MB)を読み書きします。

1

TeraCopyが使用するトリックは、読み書きを非同期にすることです。これは、別のデータが読み込まれている間にデータのブロックを書き込むことができることを意味します。

あなたの状況に最適なものを得るには、ブロックの数とそれらのブロックのサイズを慎重に検討しなければなりません。私はC++を使ってこの方法を使いました。私たちにとっては、ネットワーク共有からローカルディスクにコピーするときに最適なのは256KBの4つのブロックを使用していました。

よろしく、

Sebastiaan

1

あなたがProcess Monitorを実行する場合は、WindowsエクスプローラまたはTeraCopyを使用しているブロックサイズを確認することができます。

Vistaでは、ローカルネットワークのデフォルトのブロックサイズは約2MBで、巨大なパイプを介してファイルをより高速にコピーできます。

0

なぜホイールを改造するのですか?

状況が許せば、既存の「高速」コピーユーティリティの1つに自分自身で書き込みを行うよりも、おそらくもっと良い方法です。処理する必要のある明らかではない多数のエッジケースがあり、常に良好なパフォーマンスを得るには、多くの試行錯誤実験が必要です。

+0

スクリプト(コマンドライン)に「高速」コピーユーティリティを使用できますか? – Kiquenet

+0

少なくとも一部はスクリプト可能です - robocopyはその一例です。 – Addys

関連する問題