2

那么如果我直接使用 kernel32 来删除我的文件作为例子,它会比这个 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);

效率会更好,例如执行代码所需的时间吗?

4

3 回答 3

7

托管代码很慢是一个相当普遍的误解。通常不是,您执行的代码与 C 编译器生成的代码相同,即机器代码。它与作为操作系统功能包装器的大量 .Net 框架类尤其不相关。

就像 File 类一样。File.Delete() 方法实际上调用了 DeleteFile() winapi 函数。必然如此,这是在 Windows 上删除文件的唯一方法。.NET 框架无能为力,至少在托管操作系统可用之前是这样。这可能有一天会发生,微软的超级秘密 Midori 项目旨在开发这样一个操作系统。

但那是未来的音乐,现在它是一大块 C 代码,埋在像 Fat32 或 NTFS 这样的文件系统驱动程序中,实际上可以完成工作。它以磁盘速度运行,DeleteFile() 在文件系统驱动程序确认删除完成之前不会返回。这是非常非常缓慢的。就像老式硬盘驱动器的大约 50 毫秒,SSD 的亚毫秒范围内一样。

File.Delete()确实添加了代码,它执行了大量的错误检查。如果验证您传递的参数不为空,则检查您的代码是否未在拒绝删除文件的沙箱中运行,检查您是否未在路径中指定任何文件路径中不合法的字符,将增量路径转换为完整路径并检查它是否仍然是合法路径,检查路径字符串是否不太长,如有必要,将短 MS-Dos 8.3 名称转换为长名称。

这是一堆工作,但以微秒为单位。如果您 p​​invoke DeleteFile,那么您将跳过该代码,但充其量只会使其速度提高约 1%。您将失去的是可靠性,即如果您的代码或数据中有 oops,您将被告知的保证。带有非常清晰的异常消息,可以准确地告诉您出了什么问题。非常有价值,因为这几微秒乘以十亿仍然无法与调试不起作用的 DeleteFile() 所花费的时间和痛苦相提并论。

不要这样做。

于 2013-01-13T22:45:25.147 回答
2

唯一确定的方法是测试它。编写创建一大堆临时文件的代码,然后计算将它们全部删除所需的时间。

这里的性能考虑:

  • 使用本机 api 进行文件删除(kernel32)与
  • 不得不使用编组的性能损失。

我的直觉是,任何性能提升都会很小,如果你想得到一个的话。

于 2013-01-13T21:51:28.383 回答
2

删除操作的限制因素是执行文件系统操作,而不是将 C# 代码连接到 OS 代码的代码。您将看到这两个调用之间没有明显的区别。切换到直接在这个 API 中调用 kernel32 肯定是过早的优化。

于 2013-01-13T21:53:39.143 回答