c#中的内存压力测试
本文关键字:压力测试 内存 | 更新日期: 2023-09-27 18:16:19
我想创建一个工具来模拟内存限制以对其他应用程序进行内存压力测试。在进行了一些google搜索之后,我想出了以下代码,但是在运行此代码时,任务管理器或资源监视器没有显示内存使用的任何差异。只是一条平行线。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Win32Tute
{
unsafe class Program
{
// Heap API flags
const int HEAP_ZERO_MEMORY = 0x00000008;
// Heap API functions
[DllImport("kernel32")]
static extern int GetProcessHeap();
[DllImport("kernel32")]
static extern void* HeapAlloc(int hHeap, int flags, int size);
[DllImport("kernel32")]
static extern bool HeapFree(int hHeap, int flags, void* block);
private static int ph = GetProcessHeap();
public static void* Alloc(int size)
{
void* result = HeapAlloc(ph, HEAP_ZERO_MEMORY, size);
if(result == null) throw new OutOfMemoryException("Couldn't execute HeapAlloc");
return result;
}
public static void Free(void* block)
{
if(!HeapFree(ph, 0, block)) throw new InvalidOperationException("Couldn't free memory");
}
public static void Main(string[] args)
{
int blockSize = 1024*1024; //1mb
byte*[] handles = new byte*[1024];
Console.WriteLine("Memory before : " + (Process.GetCurrentProcess().PrivateMemorySize64/1024)/1024); // get value in Megabytes
try
{
for(int i=0; i<1024; i++)
{
handles[i] = (byte*)Alloc(blockSize);
}
}
finally
{
Console.WriteLine("Memory after : " + (Process.GetCurrentProcess().PrivateMemorySize64 / 1024)/1024);
Console.WriteLine("Finished allocating 1024MB memory....Press Enter to free up.");
Console.ReadLine();
}
try
{
for(int i=0; i<1024; i++)
{
Free(handles[i]);
}
}
finally
{
Console.WriteLine("Memory at the end : " + (Process.GetCurrentProcess().PrivateMemorySize64 / 1024)/1024);
Console.WriteLine("All allocated memory freed. Press Enter to quit..");
Console.ReadLine();
}
}
}
}
这种事情几乎总是一个坏主意。如果您成功地创建了一个消耗内存的程序,您可能会发现这样做并不会阻止其他程序的响应。虚拟内存管理器将不遗余力地保持其他程序的运行。例如,它会将占用内存的数据分页到磁盘,以便将工作程序的数据保存在它所属的内存中。如果你修改你的内存占用器,使它在内存中锁定页面(即不让页面交换出去),那么计算机将开始抖动。
你最好在你正在测试的程序中编写诊断代码,让你调用SetProcessWorkingSetSizeEx来测试程序在不同内存条件下的响应。如果你不能修改你正在测试的程序,你可以编写一个程序,获取测试程序的句柄并调用SetProcessWorkingSetSizeEx
,传递该句柄。
好了,你的文章有三个问题…
-
不需要PInvoke分配,您可以简单地使用Marshal。
-
如果您不实际使用内存,那么系统将保留它,但不一定将其放入工作集中。因此,如果您想要使用HOG内存,则需要首先分配内存,然后不断地对该内存进行读/写操作。即使这样也允许系统卸载没有被分配的页面,但是这会给内存带来压力。
-
总的来说,我不得不同意Jim Mischel的观点,这对你没有多大帮助。
对于它的价值,这里是程序更新到写入所有分配的内存,然后启动一个线程不断读取内存。这样做的缺点是一个线程/cpu将被消耗。
static void Main(string[] args)
{
int blockSize = 1024*1024; //1mb
byte*[] handles = new byte*[1024];
Console.WriteLine("Memory before : " + (Process.GetCurrentProcess().PrivateMemorySize64/1024)/1024); // get value in Megabytes
try
{
for(int i=0; i<1024; i++)
{
handles[i] = (byte*)Marshal.AllocHGlobal(blockSize);
//write to the memory
for (int off = 0; off < blockSize; off++)
*(handles[i] + off) = 1;
}
}
finally
{
//create a thread to ensure the memory continues to be accessed
ManualResetEvent mreStop = new ManualResetEvent(false);
Thread memoryThrash = new Thread(
() =>
{
int ihandle = 0;
while (!mreStop.WaitOne(0, false))
{
for (int off = 0; off < blockSize; off++)
if (*(handles[ihandle++ % handles.Length] + off) != 1)
throw new InvalidOperationException();
}
}
);
memoryThrash.IsBackground = true;
memoryThrash.Start();
Console.WriteLine("Memory after : " + (Process.GetCurrentProcess().PrivateMemorySize64 / 1024)/1024);
Console.WriteLine("Finished allocating 1024MB memory....Press Enter to free up.");
Console.ReadLine();
mreStop.Set();
memoryThrash.Join();
}
try
{
for(int i=0; i<1024; i++)
{
Marshal.FreeHGlobal(new IntPtr(handles[i]));
}
}
finally
{
Console.WriteLine("Memory at the end : " + (Process.GetCurrentProcess().PrivateMemorySize64 / 1024)/1024);
Console.WriteLine("All allocated memory freed. Press Enter to quit..");
Console.ReadLine();
}
}