C# 创建文件校验和时的性能问题

C# 创建文件校验和时的性能问题,c#,md5,checksum,C#,Md5,Checksum,我正在编写一个控制台应用程序,它通过二叉树进行迭代,并根据md5校验和搜索新的或更改的文件。 整个过程是可以接受的快(14秒约70.000个文件),但生成校验和需要约5分钟,这是相当慢 有什么改进这个过程的建议吗?我的哈希函数如下所示: private string getMD5(string filename) { using (var md5 = new MD5CryptoServiceProvider()) {

我正在编写一个控制台应用程序,它通过二叉树进行迭代,并根据md5校验和搜索新的或更改的文件。 整个过程是可以接受的快(14秒约70.000个文件),但生成校验和需要约5分钟,这是相当慢

有什么改进这个过程的建议吗?我的哈希函数如下所示:

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对象产生很大的内存压力。而是将文件作为流打开,并按块计算哈希值
  • 使用
    ComputeHash
    stream override时速度变慢的原因,因为它在内部使用非常小的缓冲区(4kb),所以选择合适的缓冲区大小(256kb或更大,通过实验找到最佳值)
  • 使用和函数计算散列值。您可以为
    outputBuffer
    参数传递null
  • 将该缓冲区用于以下文件哈希计算,因此不需要额外分配
  • 此外,您可以重用
    MD5CryptoServiceProvider
    ,但好处是值得怀疑的
  • 最后,您可以应用异步模式从流中读取数据块,这样当您计算前一个数据块的部分哈希时,操作系统将同时从磁盘读取下一个数据块。当然,这样的代码更难编写,而且您至少需要两个缓冲区(也需要重用它们),但这会对速度产生很大影响
  • 作为一个小的改进,不要检查文件是否存在。我相信,您的函数是从某个枚举调用的,并且几乎不可能同时删除该文件
以上所有内容均适用于大中型文件。如果您有很多非常小的文件,可以通过并行处理文件来加快计算速度。实际上,并行化也可以帮助处理大文件,但这取决于测量


最后,如果冲突不会给您带来太多麻烦,您可以选择成本较低的哈希算法,例如CRC。

好吧,接受的答案是无效的,因为,当然,有一种方法可以提高代码性能。但是,这对于其他一些想法是有效的)

除了磁盘I/O之外,这里的主要障碍是内存分配。以下是一些提高速度的想法:

  • 不要在内存中读取整个文件进行计算,它速度很慢,并且会通过LOH对象产生很大的内存压力。而是将文件作为流打开,并按块计算哈希值
  • 使用
    Compu时速度减慢的原因