我编写了以下程序,其目的是创建一个给定大小的文件,其中包含一些随机数据。该程序工作正常,并做它想做的事情。但是,我不明白为什么它消耗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);
}
}
}
}
答案 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()的调用。