この記事でやった検証ケースを増やし処理時間の影響を確認しました※今回はSSDではなく外付HDDにしました。またThreadクラスも使って並列処理を行い処理速度が向上するのか簡易的に確認してみました。
動作確認環境
- Windows10 x64
- コア数:4
- 論理プロセッサ:8
- RAM:8GB
- コピー元/コピー先:外付けHDDの同じドライブ内にあるフォルダー間でコピーを実施(前回は内臓SSDの同じドライブ内)
- 外付けHDDの空き容量:291GB
- VisualStudio2022
- コンソールアプリ(.NETFramework4.8)
- C#7.3
- 検証ケースが1件終わる度にコピー先のディレクトリは消去しドライブの残り容量は公平な条件となるように配慮する
- 本検証結果はメモリキャッシュが処理時間に影響を及ぼす可能性がある
- 本検証結果は検証の途中で他のアプリケーションがバックグランドで起動した等のPC状況が処理時間に影響を及ぼす可能性がある。
検証方法
サイズ:11.1MB(ディスク上のサイズ:14.8MB)
のディレクトリを1単位とし、
このディレクトリを1~32個を用意し、
- 逐次処理
- Taskクラスを用いた並列処理
- Threadクラスを用いた並列処理
の3パターンで処理速度がどの程度変わるのか確認してみた。
ソースコード(イメージ)
逐次処理
//ディレクトリにあるファイルやサブディレクトリをコピーする
for (int i1 = 0; i1 < 【コピー元のパス/コピー先のパス等の情報を格納したList】.Count; i1++)
{
【ディレクトリを1つコピーするメソッドを実行する。引数にコピー元やコピー先を指定】
}
Taskクラスを用いた並列処理
//Taskをまとめて管理するList
List<Task<int>> tasks = new List<Task<int>>();
for (int i1 = 0; i1 < 【コピー元のパス/コピー先のパス等の情報を格納したList】.Count; i1++)
{
object[] paras = { 【コピー元のパス/コピー先のパス等の情報を格納したList】.コピー元パス,【コピー元のパス/コピー先のパス等の情報を格納したList】.コピー先パス};
//ファイルやディレクトリのコピーを行う
Task<int> t = Task.Factory.StartNew(【ディレクトリを1つコピーするメソッド】, (object)paras);
tasks.Add(t);
}
//全てのTaskの完了を待つ
Task.WaitAll(tasks.ToArray());
Threadクラスを用いた並列処理
// ThreadをまとめるList
List<Thread> Threads = new List<Thread>();
//ディレクトリにあるファイルやサブディレクトリをコピーする
for (int i1 = 0; i1 < 【コピー元のパス/コピー先のパス等の情報を格納したList】.Count; i1++)
{
//ファイルやディレクトリのコピーを行う
object[] paras = { 【コピー元のパス/コピー先のパス等の情報を格納したList】.コピー元パス,【コピー元のパス/コピー先のパス等の情報を格納したList】.コピー先パス};
Thread t = new Thread(new ParameterizedThreadStart(【ディレクトリを1つコピーするメソッド】));
t.Start(paras);
Threads.Add(t);
}
//全てのスレッドの終了を待機する
for (int i1 = 0; i1 < Threads.Count; i1++)
{
Threads[i1].Join();
}
結果
メモ
一概に並列処理化さえすれば処理速度が改善できるっていうわけでもなさそう。スレッド数が少ないケースでは並列処理にすることで処理時間を改善できる傾向が見受けらるがスレッド数が増えると並列処理の方がかえって時間がかかるように見える。
今回は全て同じ容量サイズのディレクトリ(それぞれのコピー時間が同じになる想定)に対して並列処理を行った。各々のスレッドで処理させる内容が同じではないケースだと、もっと効率は落ちるかもしれない。
ファイルキャッシュとかが影響しているのか?そのあたりの知見は足りていない。それか、不定期で何らなかのアプリがバックグランドで起動した影響で、処理速度が一時的に落ちたのかもしれない。例えばスレッド数24個のケースと25個のケースで処理速度が大幅に変わっており、スレッド数の違いが原因でここまで処理時間が変わったというのはよく分からない。実際に本検証環境で本検証とは関係なくマウスでコピー&ペーストを行うときも、時間帯によってコピーにかかる時間が変わったりするのでそういう現象との関連があるのかもしれない。しかし本検証はスレッド数1の逐次→スレッド数1の並列Task→スレッド数1の並列Thread→スレッド数2の逐次・・・のように、各スレッド数毎に逐次→Task→Threadの順で実行していったので、短時間のうちにバックグラウンド処理が起動したりしなかったりするというのもよく分からない。
この記事では、並列処理にすればそれなりに処理時間が改善されたが、今回はそこまでの大幅な改善という結果にはならなかった。前回は同じSSD内部でコピーを行ったことも影響していたのかもしれない。今回は外付けのHDDの同一のドライブの中でコピーを実施した。
一概に並列処理化すればいいわけでなく、機能によって並列化すべきか検討する必要がありそう。