为什么我的SelectMany linq语句消耗大量内存

时间:2015-02-03 22:04:23

标签: c# linq out-of-memory

我有一个递归函数,用于散列目录和所有子目录。我使用的是SHA1,但问题并非如此。我的问题是它需要一个字节数组(可以理解)。所以我采用我的字节数组列表List<byte[]> byteFile并用bytfile.selectmany(x=>x).toarry()展平它。当我压扁我的阵列时出现问题,因为在VS调试中我得到内存不足异常。在耗尽大约220KB的程序之前扁平化。在展平之后(当没有在vs环境中运行时)编程消耗1.09GB。为什么扁平化这个字节数组列表会消耗这么多内存?如何减少内存占用。

以下是我使用

的代码
    private static byte[] GetGameHash(string path)
    {
        DirectoryInfo dir = new DirectoryInfo(path);

        List<byte[]> byteFile = new List<byte[]>();

        var dirs = dir.EnumerateDirectories();
        ReadFolderContents(dir, ref byteFile);

        //byte[] input = byteFile.SelectMany(x => x).ToArray();

        SHA1 mSha1 = new SHA1CryptoServiceProvider();
        mSha1.Initialize();
        byte[] hash = mSha1.ComputeHash(byteFile.SelectMany(x=>x).ToArray());
        mSha1.Dispose();

        byteFile.Clear();

        return hash;
    }

    private static void ReadFolderContents(DirectoryInfo directory, ref List<byte[]> files)
    {
        var dirFiles = directory.EnumerateFiles();
        foreach (var file in dirFiles)
            files.Add(System.IO.File.ReadAllBytes(file.FullName));


        var directories = directory.EnumerateDirectories();
        foreach (var dir in directories)
            ReadFolderContents(dir, ref files);
    }

2 个答案:

答案 0 :(得分:7)

如图所示的程序获取所有目录中所有文件的全部内容,并将其放入字节数组中。如果你有十亿字节的文件,那么你将得到一个十亿字节的数组。

这是解决这个问题的可怕方法。如果您尝试对超过一小部分字节的内容进行哈希处理,则应该对流进行哈希处理,而不是字节。

退后一步。您真的尝试使用此哈希解决的问题是什么?让我们专注于这里真正的问题;赔率是好的,你的策略存在一些根本性的错误,而不仅仅是内存不足这一事实。

那就是说,你写的这个简短的节目还有很多其他的问题。为什么直接拨打Dispose而不是使用using,这是惯用的?你为什么使用ref?列表已经是引用类型。为什么bytefile在超出范围之前立即被清除?当你看来所有你需要的是一个序列时,你为什么首先将它作为一个列表来实现呢?关于这个程序的一切都说&#34;不必要地使用内存&#34;到处都是,所以你使用大量内存对我来说并不奇怪。等等。您的组织中是否有C#专家可以审核您的工作?

答案 1 :(得分:1)

您正在将所有文件读入内存,并计算所有文件的哈希值。 您在内存中同时拥有所有文件。这就是为什么你的内存不足。

为什么不逐个读取文件并为每个文件计算哈希值,将单个哈希值存储在哈希值列表中,最后在哈希值上计算哈希值?