C# 正在使用的干净内存
我已经用内存流下载了这个文件。一旦文件被下载,我需要清除该内存流使用的所有内存C# 正在使用的干净内存,c#,asp.net,performance,memory,optimization,C#,Asp.net,Performance,Memory,Optimization,我已经用内存流下载了这个文件。一旦文件被下载,我需要清除该内存流使用的所有内存 context.Response.BufferOutput = true; //DecryptAndStoreInMemory decrypt a requested file and store in memory using (MemoryStream ms = DecryptAndStoreInMemory(context.Server.MapPath(path), userFileName)) {
context.Response.BufferOutput = true;
//DecryptAndStoreInMemory decrypt a requested file and store in memory
using (MemoryStream ms = DecryptAndStoreInMemory(context.Server.MapPath(path), userFileName))
{
byte[] bytesInStream = ms.ToArray();
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("Content-Length", bytesInStream.Length.ToString());
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + userFileName);
ClearStream(ms);
context.Response.BinaryWrite(bytesInStream);
context.Response.Flush();
context.Response.Close();
Array.Clear(bytesInStream, 0, bytesInStream.Length);
}
ClearStream(MemoryStream stream)
{
if(stream != null)
{
stream.Flush();
stream.Close();
stream.Dispose();
}
}
//解密文件并存储在内存流中
public MemoryStream DecryptAndStoreInMemory(string inputFilePath, string userFileName)
{
MemoryStream msOutput = null;
if (File.Exists(inputFilePath))
{
try
{
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(_password, _salt);
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (FileStream fsInput = new FileStream(inputFilePath, FileMode.Open))
{
using (CryptoStream cs = new CryptoStream(fsInput, encryptor.CreateDecryptor(), CryptoStreamMode.Read))
{
using (msOutput = new MemoryStream())
{
int data;
while ((data = cs.ReadByte()) != -1)
{
msOutput.WriteByte((byte)data);
}
}
}
}
}
return msOutput;
}
catch (CryptographicException)
{
throw new Exception("Sorry we can not serve " + userFileName + " file at this time.");
}
catch (Exception)
{
throw;
}
}
else
{
throw new Exception("Sorry we could not locate " + userFileName);
}
}
文件发送到响应后,不会释放占用的内存。这几乎是文件大小的两倍。17MB的文件占用了近40MB的内存
应该做些什么来腾出这些空间。
我试图清除字节数组,但发现它仅用0替换数组中的每个元素,使其长度保持不变。在.NET framwerk中,您无法直接控制内存使用。内存由垃圾收集器(GC)控制。当您处理了您的流并且它最终被解除引用时,它被称为dead。这意味着它将进行垃圾收集,当内存压力过高时,垃圾收集将自动发生 在绝大多数情况下,这里不需要任何优化,因为仅仅因为使用了内存,并不意味着在垃圾收集期间无法释放内存。带有GC的托管内存也不一定比非托管内存慢,因为托管内存中的新对象分配比非托管内存快(如果有足够的可用内存),因为托管内存是不分段的
您可以使用
GC.Collect()
初始化垃圾收集,但这可能会使代码的性能低于自动运行垃圾收集。而且,启动收集并不一定会减少已用内存的大小,因为GC并不总是将释放的内存返回给操作系统。在.NET framwerk中,您无法直接控制内存的使用。内存由垃圾收集器(GC)控制。当您处理了您的流并且它最终被解除引用时,它被称为dead。这意味着它将进行垃圾收集,当内存压力过高时,垃圾收集将自动发生
在绝大多数情况下,这里不需要任何优化,因为仅仅因为使用了内存,并不意味着在垃圾收集期间无法释放内存。带有GC的托管内存也不一定比非托管内存慢,因为托管内存中的新对象分配比非托管内存快(如果有足够的可用内存),因为托管内存是不分段的
您可以使用
GC.Collect()
初始化垃圾收集,但这可能会使代码的性能低于自动运行垃圾收集。并且启动一个收集并不一定会减少您使用的内存大小,因为GC并不总是将释放的内存返回给操作系统。为了避免双重缓冲,不要调用.ToArray()
;相反,您可以通过ms.GetBuffer()
访问现有缓冲区。请注意,这是超大尺寸的,因此您可能需要使用:
context.Response.BinaryWrite(ms.GetBuffer(), 0, ms.Length);
请注意,您无法确定地告诉数组离开,并且array.Clear
没有您想要的效果。清理是垃圾收集器的工作,你通常不应该弄乱它
然而!一个更好的方法是根本不要一次读取所有内容,而是:使用纯流式方法。我不知道您的
DecryptAndStoreInMemory
是如何实现的,所以我无法判断这在您的情况下是否可行,但是:通常是这样。为了避免双重缓冲,不要调用.ToArray()
;相反,您可以通过ms.GetBuffer()
访问现有缓冲区。请注意,这是超大尺寸的,因此您可能需要使用:
context.Response.BinaryWrite(ms.GetBuffer(), 0, ms.Length);
请注意,您无法确定地告诉数组离开,并且array.Clear
没有您想要的效果。清理是垃圾收集器的工作,你通常不应该弄乱它
然而!一个更好的方法是根本不要一次读取所有内容,而是:使用纯流式方法。我不知道您的
DecryptAndStoreInMemory
是如何实现的,所以我无法判断在您的情况下这是否可行,但是:通常是这样。第一道防线是垃圾收集器。如果变量ByteInstream
不再在任何地方引用,则应收集该变量并释放内存。这还假设bytesInStream
是真正的麻烦制造者。你能试着插入GC.Collect()吗代码>和GC.WaitForPendingFinalizers()代码>?在内存分析过程中,当您稍等一点时,内存消耗是否会变得更好?@MaximilianGerhardt我确实在顶部和底部编写了GC.Collect(),这会导致在下一次请求相同文件时清理内存。如果我再次请求同一个文件,那么它会释放以前使用过的内存,并再次保留内存。第一道防线是垃圾收集器。如果变量ByteInstream
不再在任何地方引用,则应收集该变量并释放内存。这还假设bytesInStream
是真正的麻烦制造者。你能试着插入GC.Collect()吗代码>和GC.WaitForPendingFinalizers()代码>?在内存分析过程中,当您稍等一点时,内存消耗是否会变得更好?@MaximilianGerhardt我确实在顶部和底部编写了GC.Collect(),这会导致在下一次请求相同文件时清理内存。如果我再次请求同一个文件,那么它会释放以前使用的内存,并再次保留内存。我已编辑了我的问题,并添加了DecryptAndStoreInMemory
方法。请看一看,让我们知道未来的任何增强。以及关于上述context.Response.BinaryWrite(ms.GetBuffer(),0,ms.Length)代码>我没有得到带有3个输入参数的BinaryWrite
方法。我只有一个采用byte[]
的方法。我已经编辑了我的问题,并添加了DecryptAndStoreInMemory
方法。请看一下并让我们知道