0

そこに重複があることは知っていますが、約 10 の方法を試しましたが、各フォルダーで返されたパスからファイルの名前を解析するのに平均で約 10 ミリ秒かかり、6 ミリ秒から 29 ミリ秒かかりましたDirectory.GetDirectories()

私が見つけた最速は ですがSystem.IO.Path.GetFileName(fullPath)、わずかな差でstring.SubString(string.LastIndexOf(@"\");

C:\私はより良いバージョンの Windows エクスプローラーを作成していますが、展開してすべてのサブ フォルダーを表示するのに約 0.5 秒かかります。0.5 秒は大したことではないように思えるかもしれませんが、Windows や、私が調べた別のプログラムは、瞬時に表示されます。

私が考えることができる唯一のことは、ファイルにインデックスを付け、インデックスをXMLとして保存することです。これは、起動時などに実行できると思います。

Windows と別のコントロールが同じ PC でどのようにこれほど高速に実行できるのか、私はただ興味があります。C# とマネージ コードはアンマネージ C++ より遅いですか?

アップデート:

ログ エントリのサンプルを次に示します。File.AppendAllText を使用すると、ファイルを開いたり閉じたりする必要がありますが、多くの操作はこれを完了するのに 1 ミリ秒しかかからないため、唯一遅い時間は次のように行われる SetDirectoryName です。

public void LoadChildNodes()
        {
            // clear the child nodes
            this.ChildPanel.Controls.Clear();

            // if this path exists
            if (Directory.Exists(this.Path))
            {
                // get the log
                WriteLogEntry("After Path Exists: " + stopWatch.Elapsed.Milliseconds.ToString());

                // get the directories for this node
                string[] tempDirectories = Directory.GetDirectories(this.Path);

                // get the log
                WriteLogEntry("After GetDirectories: " + stopWatch.Elapsed.Milliseconds.ToString());

                // if there rae one or more directories
                if ((tempDirectories != null) && (tempDirectories.Length > 0))
                {  
                    // reverse the list
                    List<string> directories = new List<string>();

                    // iterate the strings
                    foreach (string tempDirectory in tempDirectories)
                    {
                        // add this item
                        directories.Add(tempDirectory);
                    }

                    // now set the directories
                    directories.Reverse();

                    // log the time
                    WriteLogEntry("After Reverse Directories: " + stopWatch.Elapsed.Milliseconds.ToString());

                    // iterate the directory names
                    foreach (string directory in directories)
                    {
                        // log the time
                        WriteLogEntry("After Start Iterate New Directory: " + stopWatch.Elapsed.Milliseconds.ToString());

                        // create the childNode
                        ExplorerTreeNode childNode = new ExplorerTreeNode();

                        // the path for folders is the same as the name
                        string directoryName = System.IO.Path.GetFileName(directory);

                        // log the time
                        WriteLogEntry("After set directory name: " + stopWatch.Elapsed.Milliseconds.ToString());

                        // setup the node
                        childNode.SetupNode(directoryName, NodeTypeEnum.Folder, this.IconManager, this.Font, path);

                        // log the time
                        WriteLogEntry("After Setup Node" + stopWatch.Elapsed.Milliseconds.ToString());

                        // add this node
                        this.ChildPanel.Controls.Add(childNode);

                        // log the time
                        WriteLogEntry("After Add childNode to Controls: " + stopWatch.Elapsed.Milliseconds.ToString());

                        // dock to top
                        childNode.Dock = DockStyle.Top;

                        // log the time
                        WriteLogEntry("After Dock: " + stopWatch.Elapsed.Milliseconds.ToString());
                    }

                    // finished loading child nodes
                    stopWatch.Stop();
                    WriteLogEntry("Finished loading child nodes: " + stopWatch.Elapsed.Milliseconds.ToString());
                }                 
            }
        }

プロジェクトをオープンソースにするために、コントロールの購入を避けようとしていましたが、購入して実行可能ファイルのみを配布することになると思います。

パスが存在した後: 1 GetDirectories の後: 2 逆方向のディレクトリの後: 3 開始後 Iterate New Directory: 3 ディレクトリ名を設定した後: 20 Setup Node21 の後 childNode を Controls に追加した後: 21 Dock の後: 22 Start の後 Iterate New Directory: 22 設定した後ディレクトリ名: 29 セットアップ後 Node29 後 ChildNode をコントロールに追加: 30 Dock 後: 30 開始後 Iterate 新しいディレクトリ: 30 セット ディレクトリ名の後: 37 セットアップ後 Node38 後 ChildNode をコントロールに追加: 38 Dock 後: 39 Start 後 Iterate New Directory :39

4

2 に答える 2

2

あなたのアクセス時間は変です。私はあなたの本当のボトルネックがそこにあるとは思えません。たとえば、テスト アプリを実行したところ、次の結果が得られました (注: 私は SSD を使用しているため、このテストではディスク アクセス速度の影響をほぼ排除しています)。

Finding all files inside E:\ (recursive)...
Directory.GetFiles found 91731 files in 10,600 ms: 115.6 microseconds/file
Path.GetFileName parsed 91731 files in 134 ms: 1.5 microseconds/file

それはマイクロ秒です。そして、ほとんどの時間はファイルを配列にフェッチするのに費やされ、その後のファイル名の解析は簡単です。

結論としては、プロファイラー ( EQUATECなど) をダウンロードして、どこに時間が費やされているかを確認することをお勧めします。

自分で試してみたい場合のコードは次のとおりです。

class Program
{
    static void Main(string[] args)
    {
        var stopwatch = new Stopwatch();
        var path = @"E:\";

        Console.WriteLine("Finding all files inside {0} (recursive)", path);

        stopwatch.Restart();
        var allFiles = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
        stopwatch.Stop();
        Output("Directory.GetFiles found", allFiles.Length, stopwatch.ElapsedMilliseconds);

        stopwatch.Restart();
        var filenames = allFiles.Select(Path.GetFileName).ToArray();
        stopwatch.Stop();
        Output("Path.GetFileName parsed", filenames.Length, stopwatch.ElapsedMilliseconds);

        Console.Read();
    }

    private static void Output(string action, int len, long timeMs)
    {
        Console.WriteLine("{0} {1} files in {2:#,##0} ms: {3:0.0} microseconds/file", action, len, timeMs, timeMs * 1000.0 / len);
    }
}
于 2012-11-13T16:26:51.943 に答える
2

まず、Windows エクスプローラーは FAT テーブルへの直接アクセスを実装しています。これにより、かなりの速度が得られます。

次に、キャッシュと変更通知へのフックの組み合わせを使用します。これにより、他のアプリケーション/ウィンドウがいつファイルとディレクトリを作成したかを知ることができます。

起動時に開始されるため、この情報をすべて事前に取得できるため、すべてがほぼ瞬時に実行されているように見えます。

ネットワーク ドライブにアクセスすると、速度が低下することがわかります。これは、一度に 1 つのレベルしか取得せず、結果をキャッシュし、追加のアクセスで更新するためです。

最後に、あなたには何か他のことが起こっていると思います。1 つのファイル名を解析するのに 10 ミリ秒は少し極端です。

于 2012-11-13T16:12:37.243 に答える