24

I need the opposite of good, optimized code. For testing purposes I need a simple program to eat up RAM. Preferably not all memory so that the OS is non-functional, but more like something that would simulate a memory leak, using up a lot of memory and slowing down the OS, gradually, overtime.

Specifically, can anyone provide code spinets or links to tutorials I can use?

I saw this code as a suggestion on another post:

for (object[] o = null;; o = new[] { o });

But it is not quite what I am looking for as per the description above.

Please help.

Zolt
  • 2,761
  • 8
  • 43
  • 60
  • 5
    If you believe that by allocating managed memory in a loop you are going to slow down your operating system then you have many, many false beliefs about how memory works. You will not succeed until your beliefs are correct. I would start as follows: carefully describe the relationships between RAM, virtual address space, managed heap, page file and working set. Once you can describe all of those relationships correctly you will be able to write the code you need to write. – Eric Lippert Dec 13 '13 at 00:43

3 Answers3

25

Use

Marshal.AllocHGlobal(numbytes)

You can attach this to a timer. And just dont release the memory (dont call FreeHGlobal). Thats the most straighforward, controllable and predictable way to consume memory.

Marhsal.AllocHGlobal

Rotem
  • 21,452
  • 6
  • 62
  • 109
  • Learn something new every day! :) I would have done it the way @JustinPihony suggested because I had no idea about `Marshal.AllocHGlobal` – Saggio Dec 12 '13 at 19:49
  • 1
    @Rotem, you said, "Just don't release the memory". Doesn't the system automatically do this for you? How do I ensure the memory is not released? – Zolt Dec 12 '13 at 22:33
  • `static void Main(string[] args) { timer.Elapsed += new ElapsedEventHandler(timer_Elapsed); start_timer(); Console.Read(); } static void timer_Elapsed(object sender, ElapsedEventArgs e) { IntPtr hglobal = Marshal.AllocHGlobal(100000); Marshal.FreeHGlobal(hglobal); Process proc = Process.GetCurrentProcess(); Console.WriteLine(proc.PrivateMemorySize64); } private static void start_timer() { timer.Start(); }` – Zolt Dec 12 '13 at 22:33
  • @Rotem, above is my current code and it is not using up the system memory as I would like. Please help. – Zolt Dec 12 '13 at 22:35
  • 3
    Well, you're freeing the memory with FreeHGlobal, so there's no reason it should. – Rotem Dec 13 '13 at 10:15
5

The Design is Below, the Question asked for Gradually eating up memory

  1. Gradually Eats Up Memory
  2. Parameter #1 is the Memory it will Eat Up in Megabytes (ie 6000 is 6 Gigs)
  3. Parameter #2 is the Gradual Delay for each Iteration (ie 1000 is 1 second)
  4. The Commited Memory and Working Set will be around the Same

It was designed to use XmlNode as the object that takes up Memory because then the COMMITTED MEMORY (memory allocated by process in OS) and WORKING SET MEMORY (memory actually used by the process) would be the same. If a primative type is used to take up memory such as a byte[] array, then the WORKING SET usually is nothing, because the memory is not actually be used by the process even though its been allocated.

Make sure to compile in x64 under the Project Properties under the Build Tab. Otherwise if its compiled in x32 then it will get an OutOfMemory error around the 1.7Gigs limit. In x64 the Memory it eats up will be pretty "limitless".

using System;
using System.Xml;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace MemoryHog
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("    Total Memory To Eat Up in Megs: " + args[0]);
            Console.WriteLine("Millisecs Pause Between Increments: " + args[1]);            
            int memoryTotalInMegaBytes     = Convert.ToInt32(args[0]);
            int secondsToPause             = Convert.ToInt32(args[1]);

            Console.WriteLine("Memory Usage:" +     Convert.ToString(GC.GetTotalMemory(false)));

            long runningTotal = GC.GetTotalMemory(false);
            long endingMemoryLimit = Convert.ToInt64(memoryTotalInMegaBytes) * 1000 *     1000;
            List<XmlNode> memList = new List<XmlNode>();
            while (runningTotal <= endingMemoryLimit)
            {
                XmlDocument doc = new XmlDocument();
                for (int i=0; i < 1000000; i++)
                {
                    XmlNode x = doc.CreateNode(XmlNodeType.Element, "hello", "");
                    memList.Add(x);
                }
                runningTotal = GC.GetTotalMemory(false);
                Console.WriteLine("Memory Usage:" +     Convert.ToString(GC.GetTotalMemory(false)));
                Thread.Sleep(secondsToPause);
            }
            Console.ReadLine();
            
        }

    }
}
Community
  • 1
  • 1
CodeCowboyOrg
  • 2,983
  • 1
  • 15
  • 12
2

The easiest way to create memory leaks in C# is by attaching to events and not detaching. That is what I would do at least. Here is a SO that talks about this

Community
  • 1
  • 1
Justin Pihony
  • 66,056
  • 18
  • 147
  • 180
  • 1
    While it would indeed create a memory leak, it wouldn't consume a lot of memory, unless the object that is hold in memory because of the event consumes a lot memory _itself_. – ken2k Dec 12 '13 at 18:58