10

如果您有兴趣,这里也提出了一个非常类似的问题,但是我们将看到该问题的公认答案并非总是如此(而且我的应用程序使用模式也并非如此)。

性能确定代码由 FileStream 构造函数(用于打开文件)和 SHA1 哈希(.Net 框架实现)组成。该代码几乎是我在上面链接到的问题中提出的 C# 版本。

情况1:应用程序第一次或第N次启动,但目标文件集不同。现在告诉应用程序计算以前从未访问过的文件的哈希值。

  • ~50ms
  • 80% FileStream 构造函数
  • 18% 哈希计算

案例 2:应用程序现在完全终止,并重新启动,要求计算相同文件的哈希:

  • ~8ms
  • 90% 哈希计算
  • 8% FileStream 构造函数

问题
我的应用程序始终在用例 1中。永远不会要求它重新计算已经访问过一次的文件的哈希值。

所以我决定速率的步骤是 FileStream Constructor!我能做些什么来加快这个用例的速度吗?

谢谢你。

PS Stats 是使用 JetBrains 分析器收集的。

4

5 回答 5

3

...但具有不同的目标文件集。

关键短语,您的应用程序将无法利用文件系统缓存。就像在第二次测量中所做的那样。目录信息不能来自 RAM,因为它还没有被读取,操作系统总是不得不回退到磁盘驱动器,这很慢。

只有更好的硬件才能加快速度。50 毫秒大约是主轴驱动器所需的标准时间量,20 毫秒大约是此类驱动器可以达到的最低时间。读卡器磁头寻道时间是硬机械限制。这在今天很容易被击败,SSD 广泛可用且价格合理。唯一的问题是,当你习惯了它,你就再也不会退缩了:)

于 2018-08-06T14:22:21.863 回答
1

文件系统和/或磁盘控制器将缓存最近访问的文件/扇区。

决定速率的步骤是读取文件,而不是构造FileStream对象,当数据在缓存中时,第二次运行会明显更快,这是完全正常的。

于 2009-11-02T20:40:33.967 回答
1

如前所述,文件系统有自己的缓存机制,它会扰乱您的测量。

但是,FileStream构造函数执行几个任务,第一次是昂贵的并且需要访问文件系统(因此可能不在数据缓存中的某些内容)。出于解释的原因,您可以查看代码,并看到这些CompatibilitySwitches类用于检测子功能的使用。与这个类一起,反射在直接(访问当前程序集)和间接(对于 CAS 保护部分、安全链接需求)中都被大量使用。反射引擎有自己的缓存,当自己的缓存为空时需要访问文件系统。

这两个测量值如此不同,感觉有点奇怪。我们目前在我们的机器上安装了类似的东西,这些机器配备了配置了实时保护的防病毒软件。在这种情况下,杀毒软件在中间,缓存是第一次命中还是未命中取决于此类软件的实现。

由于已知的解码漏洞,防病毒软件可能决定积极检查某些图像文件,例如 PNG。此类检查会引入额外的减速并在最外层的 .NET 类(即FileStream该类)中计算时间。

使用本机符号和/或内核调试进行分析,应该会给你更多的见解。

根据我的经验,您所描述的内容无法减轻,因为我们无法控制多个隐藏层。根据您的使用情况,我现在还不是很清楚,您可以将应用程序转换为服务,因此您可以更快地处理所有后续请求。或者,您可以将多个请求批处理到一个调用中,以实现摊销降低成本。

于 2018-08-06T13:07:55.553 回答
1

偏离轨道的建议,但这是我做了很多的事情,我们的分析速度提高了 30% - 70%:

缓存


编写另一段代码:

  • 遍历所有文件;
  • 计算哈希;和,
  • 将其存储在另一个索引文件中。

现在,不要FileStream在应用程序启动时调用构造函数来计算哈希。相反,打开(预期要小得多的)索引文件并从中读取预先计算的哈希值。

此外,如果这些文件是每次在您的应用程序启动之前新创建的日志等文件,请在文件创建器中添加代码以使用新创建文件的哈希值更新索引文件。

这样,您的应用程序始终只能从索引文件中读取哈希值。


我同意@HansPassant 的建议,即使用 SSD 使您的磁盘读取速度更快。这个答案和他的答案是互补的。您可以同时实施这两种方法以最大限度地提高性能。

于 2018-08-06T15:31:45.397 回答
-1

您应该尝试使用本机FILE_FLAG_SEQUENTIAL_SCAN,您必须 pinvokeCreateFile才能获得句柄并将其传递给FileStream

于 2009-11-02T21:02:59.470 回答