我有一个我一直在研究的数据解析应用程序并且给出了它正在读取的文本文件的大小,控制内存使用是获得良好性能的关键。这里的两部分策略首先测量每个文件对总和有多大的RAM,但它还需要知道在给定时间点应用程序可用的RAM量。如果有足够的RAM可用,则应用程序选择在内存中进行处理。否则,它会切换到执行磁盘上所有或大部分操作的模式。
测量文件对内存使用的贡献是快速而简单的:
static Int64 GetSizeInMemory(string path)
{
//THIS CODE IS SPEEDY
Int64 r = ((Func<Int64>)(
() =>
{
try
{
using (Stream s = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(s, File.ReadAllLines(path));
return s.Length;
}
}
catch
{
//this file is way too big
return -1;
}
}
))();
GC.Collect();
GC.WaitForPendingFinalizers();
return r;
}
然而,测量可用内存总量是缓慢而困难的。在这种情况下,我尝试通过捕获堆栈溢出错误来实现这一点,在我的想法中应该给出最可靠的数据。
static Int64 GetMaxAllowedMemory()
{
//THIS CODE IS SLOW
Int64 r = ((Func<Int64>)(
() =>
{
byte[] b = new byte[]{};
Int64 rs = 0;
while (true)
{
try
{
Array.Resize<byte>(ref b, b.Length + 1);
b[b.Length - 1] = new byte();
rs = b.Length;
} catch (Exception e) {
break;
}
}
b = null;
return rs;
}
))();
GC.Collect();
GC.WaitForPendingFinalizers();
return r;
}
我应该在这里使用更好的方法吗?
请注意我已经在Stack Overflow上查看过类似于此问题的一些问题,但大多数问题仅涉及获取计算机上可用内存总量的数字,而不是与运行时允许的.NET进程的最大RAM量相同。
更新
收到答复后,我想出了以下内容,可以让我获得应用程序可用的RAM总量。
static Int64 GetMemoryFailPoint()
{
Int64 r = ((Func<Int64>)(
() =>
{
int rs = 1;
while (true)
{
try
{
using (new System.Runtime.MemoryFailPoint(rs))
{
}
}
catch {
break;
}
rs++;
}
return Convert.ToInt64(rs) * 1000000;
}
))();
return r;
}
答案 0 :(得分:1)
您可以尝试使用MemoryFailPoint
类:
try
{
using (new System.Runtime.MemoryFailPoint(1024)) // 1024 megabytes
{
// Do processing in memory
}
}
catch (InsufficientMemoryException)
{
// Do processing on disk
}
基于此original post。
答案 1 :(得分:0)
不是将整个文件读入内存并查看它是否失败,您可以使用MemoryFailPoint
来检查是否有足够的ram可用于使用内存处理来执行内存中处理磁盘上的文件。
void ProcessFile(string path)
{
try
{
var fileInfo = new FileInfo(path);
var fileSizeInMb = (int)(fileInfo.Length >> 20);
using (new System.Runtime.MemoryFailPoint(fileSizeInMb))
{
// Do processing in memory
}
}
catch (InsufficientMemoryException)
{
// Do processing on disk
}
}