Стресс-тестирование памяти в C # - PullRequest
5 голосов
/ 02 декабря 2011

Я хочу создать инструмент для имитации ограничений памяти для стресс-тестирования памяти других приложений. Я пришел к следующему коду после прохождения некоторых поисков в 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();
            }
        }
    }
}

Ответы [ 2 ]

4 голосов
/ 13 декабря 2011

Подобные вещи почти всегда плохая идея.Если вам удастся создать программу, которая жует память, вы, вероятно, обнаружите, что это не помешает другой программе ответить.Менеджер виртуальной памяти приложит все усилия, чтобы другая программа работала.Например, он будет записывать данные вашей памяти на диск, чтобы сохранить данные рабочей программы в памяти, где они находятся.И если вы измените свою память, чтобы она блокировала страницы в памяти (то есть не позволяла выгружаться страницам), компьютер начал работать с перебоями.тестируемая программа, которая позволит вам вызвать SetProcessWorkingSetSizeEx , чтобы проверить, как программа реагирует на изменение состояния памяти.Если вы не можете изменить тестируемую программу, вы можете написать программу, которая получает дескриптор тестовой программы и вызывает SetProcessWorkingSetSizeEx, передавая этот дескриптор.

3 голосов
/ 13 декабря 2011

Хорошо, так что три вопроса в вашем посте ...

  1. Нет необходимости в PInvoke распределении, вы можете просто использовать Marshal.AllocHGlobal и FreeHGlobal для этого.

  2. Если вы на самом деле не используете память, то система зарезервирует ее, но не обязательно поместит ее в рабочий набор.Поэтому, если вы хотите использовать память HOG, вам сначала нужно выделить память, а затем постоянно читать / записывать в эту память.Даже это позволит системе выгружать страницы, которые не распределяются, но это будет оказывать давление на память.

  3. Вообще я должен согласиться с Джимом Мишелем, это не собираетсяочень поможет вам.

Для этого стоит программа, обновленная для записи во всю выделенную память, а затем для запуска потока, который постоянно читает память.Обратной стороной этого является то, что один поток / процессор будет потребляться этим.

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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...