测量应用程序可用的RAM总量

本文关键字:RAM 总量 应用程序 测量 | 更新日期: 2023-09-27 18:15:07

我一直在开发一个数据解析应用程序,考虑到它正在读取的文本文件的绝对大小,控制内存使用是获得良好性能的关键。这里的两部分策略首先测量每个文件将为总数贡献多少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;
    }

我应该在这里使用更好的方法吗?

请注意我看过许多类似于堆栈溢出的问题,但大多数只处理获得计算机上可用RAM总量的数字,这与。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;
    }

测量应用程序可用的RAM总量

您可以尝试使用MemoryFailPoint类:

try
{
    using (new System.Runtime.MemoryFailPoint(1024)) // 1024 megabytes
    {
        // Do processing in memory
    }
}
catch (InsufficientMemoryException)
{
    // Do processing on disk
}

根据原文改编

与其将整个文件读入内存并查看它是否失败,不如使用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
    }
}