2012-11-13 46 views
0

我知道那裏有重複的內容,但我嘗試了大約10個方法,它需要6ms到29ms之間,每個文件夾平均需要大約10ms才能解析從Directory.GetDirectories()返回的路徑中取出文件的名稱。快速檢索不含完整路徑的子文件夾名稱的方法

我發現的最快的是System.IO.Path.GetFileName(fullPath),但只有string.SubString(string.LastIndexOf(@"\")的短邊;

我正在寫一個更好的Windows資源管理器版本,但它需要大約半秒來展開C:\並顯示所有子文件夾。半秒鐘可能看起來並不多,但Windows和我看到的另一個程序會立即出現。

我能想到的唯一方法是索引文件並將索引存儲爲XML,我想這可以在啓動時完成或執行某些操作。

我只是好奇,Windows和另一個控件如何在同一臺PC上做到這麼快。 C#和託管代碼比非託管C++慢嗎?

更新:

這裏是日誌條目的示例中,我體會到使用File.AppendAllText必須打開和關閉文件,但很多操作只需要1個milisecond做到這一點,所以只能緩慢時間是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 後開始迭代新目錄:3 後集的目錄名稱:20 後安裝Node21 添加childNode後控制:21 後碼頭:22 後開始迭代新目錄:22 後集的目錄名稱:29 安裝後Node29 添加後childNode對照:30 碼頭後:30 開始迭代新目錄後:30 後集的目錄名稱:37 安裝之後Node38 添加後childNode對照:38 碼頭後:39 開始迭代新目錄後:39

+0

很可能他們使用的低級代碼來獲取這些東西。可能有一些COM庫可以使用 - 但最終我認爲微軟將會獲得很好的瀏覽器...... – MoonKnight

+0

「C#和託管代碼比非託管C++慢嗎?」是的,非常非常。其他人已經說得更好了,我發現的最佳答案(在獲得特定信息的Google之後)是http://stackoverflow.com/questions/4257659/c-sharp-versus-c-performance –

+1

您可能需要背景工作人員構建一個級別下的存儲緩存。 –

回答

2

首先,Windows資源管理器實現的FAT表的直接訪問。這提供了相當數量的速度。

其次,它將緩存和掛鉤組合使用到更改通知中。這允許它知道其他應用程序/窗口何時創建文件和目錄。

因爲它是在啓動時啓動的,所以它能夠預先獲得所有這些信息,這使得它看起來一切都運行得很快。

您會注意到訪問網絡驅動器時速度變慢。這是因爲它一次只能檢索一個級別,同時緩存結果並刷新其他訪問。

最後,我想你還有其他事情正在進行。 10ms解析單個文件名是有點極端的。

+0

這似乎是一個很好的答案,但沒有回答最後一個問題:「C#和託管代碼比非託管C++慢嗎?」這是YES – emartel

+2

@emartel:實際上它比簡單的是/否更復雜。見http://stackoverflow.com/questions/3016451/performance-of-managed-c-vs-unmanaged-native-c – NotMe

+0

夠公平!我對託管代碼的有限經驗似乎指出它比較慢,但如果不是這種情況,這個鏈接應該是答案的一部分:) – emartel

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); 
    } 
} 
相關問題