- ベストアンサー
[C#]このコードはもっと速くなると思いますか?
フォルダ内の全ファイルを取得する、以下のようなコードを組んでみました。 このコードではFileInfoを配列に入れていますが、厳密には「ファイル名」「ファイルパス」「ファイルサイズ」「更新日時」を格納したリストが欲しいです。 using System; using System.Collections.Generic; using System.Diagnostics; static void Main(string[] args) { Stopwatch sw = new Stopwatch(); sw.Start(); //windows xpを使っています DirectoryInfo di = new DirectoryInfo(@"C:\WINDOWS"); test(di); sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); } //ファイル情報を格納する配列 static List<FileInfo> list = new List<FileInfo>(); //全ファイルの探索 static void test(DirectoryInfo di) { foreach(FileInfo fi in di.GetFiles()) list.Add(fi); foreach(DirectoryInfo ddi in di.GetDirectories()) test(ddi); } ちなみに私の環境では1000ms前後の結果になります。 このリストを取得するのに、さらにスピードアップさせる方法はあると思いますか? どんな些細な事でも良いので答えて下さるとありがたいです。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
こんばんは。 手っ取り早くは、「foreach」を「while」又は「for」に差し替える、と言った所でしょうか。 当方が書店でC#の書籍を立ち読みした際に、「foreach」は「for」と比較して実行コストがかかる、と記載されていたと記憶しています。 日本のサイトから探し出せなかったので、海外サイトになりますが、 ・「Which loop is better in performance - foreach or for or while?」 http://forums.asp.net/t/1041090.aspx 100000回ループで、 for->0.0003745秒 while->0.0003641秒 foreach->0.0009076秒 と言う計測結果が出ています。 ・「C# Foreach Loop Optimization」 http://dotnetperls.com/foreach-loop-optimization こちらの方は、メンバ変数ではなく、ローカル変数へコピーしたものを「foreach」で使用すると僅かながらも速度が改善すると言うネタの様です。 その他のネタとしては、「FindNextFile()API」等を直接呼び出してみる、と言ったところです。 但し、P/Invokeを始め、C言語同等のプレーンな構造体を用意する必要があり、unsafeキーワードの使用も避けられそうにありません。コードもややこしくなります。 勿論、内部的にはNetFrameworkがAPIを呼び出している筈ですが、API呼び出しに到達するまでにはそれなりに時間がかかっているでしょうから、時間に余裕があれば実験してみる価値はあるかもしれません。 ツリービューにディレクトリ構造とファイルを表示する場合は、クリックされたフォルダから+2階層先まで検索して、こっそりとツリーアイテムを追加して行く事で容易に最適化が行えるのですが、ファイル名等をリストコレクションに収めて行きたいと言う事の様ですので、これ以上は打つ手なし、でしょうか。
その他の回答 (2)
- bluecampus
- ベストアンサー率66% (138/209)
ちなみにコマンドプロンプトで dir /s C:\Windows > 適当なファイルのパス だとどれぐらいかかりますか? その時間とあまり変わらないのであればそんなに早くできないのかなぁと。
お礼
なるほど、その手がありましたか。 というわけで、早速試してみましたけど体感的にはあまり変わらない感じですね。 うーん、これ以上の速度アップは難しそうですね。 これを結論として締めさせて頂きます、ありがとうございました。
- hitomura
- ベストアンサー率48% (325/664)
> foreach(FileInfo fi in di.GetFiles()) > list.Add(fi); の部分を list.AddRange(di.GetFiles()); に変えてみたらどうでしょうか。
お礼
回答ありがとうございます。 こんな質問に答えてくれるような奇特な人はいないだろう、と思ってたので正直嬉しいです。 しかし残念ながら速度アップには至りませんでした。 AddRangeの存在をすっかり忘れてたので、この回答を見た時の衝撃はかなりものだったんですけど。
お礼
多数のご提案、ありがとうございます。 残念ながら上二つは、速度アップに繋がりませんでした。 (http://ufcpp.net/study/csharp/sp_foreach.html 余談ですが上記リンク先の後ろ2行によると、配列のforeachはfor相当のコードに最適化されるようですね) FindNextFile()についてはP/Invokeという聞き慣れない単語、さらにunsafeを使うという事ですので、すみませんがお礼だけ先にするという形を取らせて貰います。 私程度の頭で理解出来るか分かりませんが、少しずつでも調べて組んでみたいと思います。 >これ以上は打つ手なし、でしょうか。 うーん、なるほどそうです。 いや十分すぎるほど参考・勉強になりました。