2013-01-13 43 views
2

因此,如果我直接使用kernel32刪除我的文件作爲例子,它會更有效地替代這個C#API嗎?在C#中使用託管API的高效替代方案?

System.IO.File.Delete(string Path); 

如果我輸入的dll像這樣,只是使用的DeleteFile( 「C:..」):

[DllImport("kernel32.dll", SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool DeleteFile([MarshalAs(UnmanagedType.LPWStr)]string lpFileName); 

會不會是在效率研究e.g時間更需要執行的代碼?

+2

看起來像微型優化。你真的需要非常快速地刪除文件嗎? – Oded

+2

刪除文件是一個佔用CPU很少的I/O操作,我懷疑你根本看不到任何時間上的差異。 –

回答

7

託管代碼很慢是一個相當普遍的誤解。通常情況下,您不會執行與C編譯器生成的代碼相同的代碼。這與大量的那些.NET操作系統功能的包裝類框架無關。

和File類一樣。 File.Delete()方法實際上是調用DeleteFile()winapi函數。必須如此,這是在Windows上刪除文件的唯一方法。 .NET框架沒有什麼可以做,至少直到託管操作系統變得可用。實際上這可能會發生在某一天,微軟的超級祕密Midori項目旨在開發這樣一個操作系統。

但是,這是未來的音樂,現在它是一大塊C代碼,埋在像Fat32或NTFS這樣的文件系統驅動程序中,實際上完成了這項工作。它以磁盤速度運行,直到文件系統驅動程序確認刪除完成後,DeleteFile()纔會返回。這是非常非常緩慢的。對於老式硬盤來說,大約需要50毫秒,而在SSD的亞毫秒範圍內。

File.Delete()確實添加代碼,它執行大量的錯誤檢查。如果驗證您傳遞的參數不爲空,請檢查您的代碼是否未在拒絕文件刪除權限的沙箱中運行,檢查是否未在文件路徑中指定路徑中任何不合法的字符,將增量路徑轉換爲完整路徑並檢查它是否仍然是合法路徑,檢查路徑字符串是否不太長,如果需要,將短的MS-Dos 8.3名稱轉換爲長名稱。

這是一堆工作,但這是測量在微秒。如果您捏住DeleteFile,那麼您將跳過該代碼,但只會使其速度加快1%左右。你將失去的是可靠性,保證如果你的代碼或數據中有哎呀,你會被告知它。用非常明確的例外信息告訴你到底發生了什麼問題。非常有價值,因爲那幾微秒乘以十億,仍然不能滿足您調試DeleteFile()時所花費的時間和痛苦。

不要這樣做。

+0

明智的答案。 –

+0

謝謝你在這個答案中的時間和精力。 –

2

要知道肯定的唯一方法就是測試它。編寫創建一大堆臨時文件的代碼,然後再花費多長時間刪除所有臨時文件。

性能方面的考慮在這裏:

  • 使用本機API的文件刪除(kernel32)VS
  • 性能損失不必使用編組任何可能的性能增益。

這將是我的直覺,如果你想得到一個,任何性能增益都會很小。

+1

雖然這通常是正確的,但在這種特殊情況下,我必須採取「任何開銷,爲了所有實際目的,完全通過操作成本來減輕」。此外,標準的.NET方法必須在某種程度上與本地操作系統進行通信。 – 2013-01-13 22:37:55

+1

我完全同意;這肯定會是文件I/O,這會讓你放慢速度,因此任何性能提升都是微不足道的。 –

3

刪除操作的限制因素是執行文件系統操作,而不是將C#代碼連接到OS代碼的代碼。這兩個調用之間沒有明顯的區別。切換到在這個API中直接調用kernel32肯定是一個過早的優化。