C# 创建文件校验和时的性能问题
我正在编写一个控制台应用程序,它通过二叉树进行迭代,并根据md5校验和搜索新的或更改的文件。 整个过程是可以接受的快(14秒约70.000个文件),但生成校验和需要约5分钟,这是相当慢 有什么改进这个过程的建议吗?我的哈希函数如下所示:C# 创建文件校验和时的性能问题,c#,md5,checksum,C#,Md5,Checksum,我正在编写一个控制台应用程序,它通过二叉树进行迭代,并根据md5校验和搜索新的或更改的文件。 整个过程是可以接受的快(14秒约70.000个文件),但生成校验和需要约5分钟,这是相当慢 有什么改进这个过程的建议吗?我的哈希函数如下所示: private string getMD5(string filename) { using (var md5 = new MD5CryptoServiceProvider()) {
private string getMD5(string filename)
{
using (var md5 = new MD5CryptoServiceProvider())
{
if (File.Exists(@filename))
{
try
{
var buffer = md5.ComputeHash(File.ReadAllBytes(filename));
var sb = new StringBuilder();
for (var i = 0; i < buffer.Length; i++)
{
sb.Append(buffer[i].ToString("x2"));
}
return sb.ToString();
}
catch (Exception)
{
Program.logger.log("Error while creating checksum!", Program.logger.LOG_ERROR);
return "";
}
}
else
{
return "";
}
}
}
私有字符串getMD5(字符串文件名)
{
使用(var md5=new MD5CryptoServiceProvider())
{
如果(File.Exists(@filename))
{
尝试
{
var buffer=md5.ComputeHash(File.ReadAllBytes(filename));
var sb=新的StringBuilder();
for(var i=0;i
要创建哈希,必须读取文件的最后一个字节。因此,此操作受磁盘限制,而不是CPU限制,并且与文件大小成比例地扩展。多线程处理没有帮助
除非FS能够以某种方式为您计算和存储哈希,否则无法加快速度。您取决于FS为您跟踪更改所做的工作
通常,检查“已更改文件”(如备份例程)的程序不计算Hashvalue,原因正是此。他们仍然可以计算并存储它以进行验证,但仅此而已
除非用户进行了严重的(NTFS驱动程序加载级别)破坏,否则文件大小的“上次更改”日期足以检测更改。也许还可以检查存档位,但现在很少使用
这类场景(列出文件并处理它们)的一个小改进是使用“”而不是列出文件。但在14秒/5分钟的处理过程中,这将不会产生任何相关影响。为了创建哈希,您必须读取文件的每一个最后字节。因此,此操作受磁盘限制,而不是CPU限制,并且与文件大小成比例地扩展。多线程处理没有帮助 除非FS能够以某种方式为您计算和存储哈希,否则无法加快速度。您取决于FS为您跟踪更改所做的工作 通常,检查“已更改文件”(如备份例程)的程序不计算Hashvalue,原因正是此。他们仍然可以计算并存储它以进行验证,但仅此而已 除非用户进行了严重的(NTFS驱动程序加载级别)破坏,否则文件大小的“上次更改”日期足以检测更改。也许还可以检查存档位,但现在很少使用
这类场景(列出文件并处理它们)的一个小改进是使用“”而不是列出文件。但是在14秒/5分钟的处理时间里,这将不会产生任何相关的影响。好吧,接受的答案是无效的,因为,当然,有一种方法可以提高代码性能。但是,这对于其他一些想法是有效的) 除了磁盘I/O之外,这里的主要障碍是内存分配。以下是一些提高速度的想法:
- 不要在内存中读取整个文件进行计算,它速度很慢,并且会通过LOH对象产生很大的内存压力。而是将文件作为流打开,并按块计算哈希值
- 使用
stream override时速度变慢的原因,因为它在内部使用非常小的缓冲区(4kb),所以选择合适的缓冲区大小(256kb或更大,通过实验找到最佳值)ComputeHash
- 使用和函数计算散列值。您可以为
参数传递nulloutputBuffer
- 将该缓冲区用于以下文件哈希计算,因此不需要额外分配
- 此外,您可以重用
,但好处是值得怀疑的MD5CryptoServiceProvider
- 最后,您可以应用异步模式从流中读取数据块,这样当您计算前一个数据块的部分哈希时,操作系统将同时从磁盘读取下一个数据块。当然,这样的代码更难编写,而且您至少需要两个缓冲区(也需要重用它们),但这会对速度产生很大影响
- 作为一个小的改进,不要检查文件是否存在。我相信,您的函数是从某个枚举调用的,并且几乎不可能同时删除该文件
最后,如果冲突不会给您带来太多麻烦,您可以选择成本较低的哈希算法,例如CRC。好吧,接受的答案是无效的,因为,当然,有一种方法可以提高代码性能。但是,这对于其他一些想法是有效的) 除了磁盘I/O之外,这里的主要障碍是内存分配。以下是一些提高速度的想法:
- 不要在内存中读取整个文件进行计算,它速度很慢,并且会通过LOH对象产生很大的内存压力。而是将文件作为流打开,并按块计算哈希值
- 使用
Compu时速度减慢的原因