FileStream和内存使用情况

时间:2010-10-21 20:12:28

标签: .net file-io .net-4.0 memory-management filestream

我编写了以下程序,其目的是创建一个给定大小的文件,其中包含一些随机数据。该程序工作正常,并做它想做的事情。但是,我不明白为什么它消耗5GB的RAM(参见我的任务管理器的截图)。当我用随机数据编写文件时,我不是在创建新对象。我错过了什么?我希望这个程序根本没有记忆。

我现在面临的一个大问题是,在文件生成的中间,机器正在死...

class Program
{
    static void Main(string[] args)
    {
        CreateFile("test.dat", 10 * 1024 * 1024);
    }

    public static void CreateFile(string path, long approximativeFileSizeInKb)
    {
        RandomNumberGenerator randomNumber = RandomNumberGenerator.Create();

        byte[] randomData = new byte[64 * 1024];

        int numberOfIteration = 0;
        randomNumber.GetNonZeroBytes(randomData);

        using (FileStream fs = File.Create(path, 64 * 1024))
        {
            while (numberOfIteration++ * 64 < approximativeFileSizeInKb)
            {
                fs.Write(randomData, 0, randomData.Length);
            }
        }
    }
}

alt text alt text

6 个答案:

答案 0 :(得分:6)

更改您的行:

using (FileStream fs = File.Create(path, 64 * 1024))

using (FileStream fs = File.Create(path, 64 * 1024, FileOptions.WriteThrough))

并了解它对您的影响。

答案 1 :(得分:5)

操作系统始终缓冲文件系统写入。

您正在调用FileSystem.Write,而不是硬件可以处理写入,因此操作系统会缓存您的所有写入。

即使您调用了FileSystem.Flush,您的写入速度仍然比硬件处理写入速度快。

获得更快的硬盘子系统。首选RAID控制器,其中大量板载内存连接到大型RAID 5或6阵列,基于服务器的硬盘驱动器,64MB缓存设置为写入缓冲。

(为了缓解此行为,请将标记FileOptions.WriteThrough添加到您的File.Create调用中。)

答案 2 :(得分:1)

Windows似乎正在使用文件系统缓存......它不是应用程序

答案 3 :(得分:1)

我从各个站点将它拼凑在一起....问题是Windows仍然使用writethrough选项缓存所有内容。因此,如果您使用标准FileStream,您的“免费”内存会下降,如果尝试使用极大文件执行某些操作并同时捕获高速率数据,则可能会出现问题。当你关闭你的应用程序时,Windows仍然有文件缓存,顺便说一下。这对于你想写的文件是好的,而且忘记了... .Net似乎认为你不需要。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

namespace ConsoleApplication2
{
    class Program
    {
        [DllImport("KERNEL32", SetLastError = true)]
        public extern static int CloseHandle(IntPtr hObject);
        [DllImport("kernel32", SetLastError = true)]
        public static extern unsafe IntPtr CreateFile(
            string FileName,           // file name 
            uint DesiredAccess,        // access mode 
            uint ShareMode,            // share mode 
            IntPtr SecurityAttributes, // Security Attr 
            uint CreationDisposition,  // how to create 
            uint FlagsAndAttributes,   // file attributes 
            IntPtr hTemplate // template file   
            );
        static void Main(string[] args)
        {
            const uint FILE_FLAG_NO_BUFFERING = 0x20000000;
            const uint FILE_FLAG_WRITE_THROUGH = 0x80000000;
            Random r = new Random(0);
            IntPtr f = CreateFile(@"e:\test\temp.bin",
                             (uint)FileAccess.Write,
                             (uint)FileShare.None,
                             IntPtr.Zero,
                             (uint)FileMode.Create,
                              FILE_FLAG_NO_BUFFERING,
                             IntPtr.Zero);
            using (FileStream fs = new FileStream(f,FileAccess.Write,false,1024*1024))
            {
                int blocksize = 1024 * 1024;
                byte[] val = new byte[blocksize];
                for (int i = 0; i < blocksize; i++)
                {
                    val[i] = 1;
                }
                while (true)
                {
                    for (int i = 0; i < 1000; i++)
                    {
                        for (int j = 0; j < blocksize; j++)
                        {
                            fs.WriteByte(val[i]);
                        }
                    }
                    Console.WriteLine("Enter s to stop");
                    ConsoleKeyInfo k = Console.ReadKey();
                    if (k.KeyChar == 's')
                    {
                        break;
                    }
                }
            }
            CloseHandle(f);
            Console.WriteLine("done");
            Console.ReadKey();
        }
    }
}

答案 4 :(得分:0)

FileStream维护一个内存缓冲区,允许程序尽可能快地输出。你的程序可以将数据填充到缓冲区中,而不是将缓冲区写入磁盘,这是内存跳转的地方。

但实际使用的内存确实看起来不过一点点了;你正在生成一个10MB的文件(64KB块)并使用大约5GB的内存来实现这一目标。这个程序还有什么比代码片段中的内容还要多吗?你多次运行它吗?

答案 5 :(得分:0)

和Gonzalo一样,我在我的系统上运行了你的代码,只看到内存使用量增加了1GB。

您是否开启了防病毒软件? AV可能正在扫描.dat文件,因为它正在被写入,导致数据在扫描发生时被缓存在内存中,这导致内存使用量的大量增加。如果您怀疑AV是问题的一部分,请尝试将文件扩展名更改为.dat以外的其他内容(例如.txt)。

另一件事是在fs.Write(...)之后添加对fs.Flush()的调用。