Tag Archives: chaos monkey

Chaos Monkey – Part 3 – Consuming Memory

Continuing from previous posts on programs that generally do your machine no good at all, I thought it might be an idea to have a look what I could do to the available memory. The use case here being that you want to see how your application can function when in competition with either one high-memory process, or many smaller ones.

To accomplish this, we’re going to create a list of strings – since strings are notoriously bad for memory anyway. The first thing to note here is that a single character takes up 16 bits, which is 2 bytes.

The second this is how to check the system’s available memory:

        private static System.Diagnostics.PerformanceCounter ramCounter =
            new System.Diagnostics.PerformanceCounter("Memory", "Available MBytes");

        private static long GetRemainingMemory()
        {
            return ramCounter.RawValue;
        }

Finally, you need to be aware that you can only use up all the memory in your machine (assuming you have more than 2GB) if you run the app in x64 mode. If you have less then you probably don’t need this article to simulate what low memory feels like.

There is a pretty big caveat to doing this; once you actually run out of memory; it takes a good few minutes for the system to catch up; even when you terminate the process. Consequently, the code that I use allows you to specify a “remaining memory”; here’s the main function:

        static void Main(string[] args)
        {
            long remainingMemory = int.Parse(args[0]);

            // Determine how much memory there is
            long memoryLeft = GetRemainingMemory();
            Console.WriteLine("Consuming memory until {0} is left", remainingMemory);

            // Calculate how much memory to use
            long removeMemory = memoryLeft - remainingMemory;

            // Call the function to consume the memory
            Console.WriteLine("Consuming {0} memory", removeMemory);
            ConsumeMemory(removeMemory, 1000);

            // Free the memory
            Console.WriteLine("Press any key to free memory");
            Console.ReadLine();
            FreeMemory();

            Console.ReadLine();
        }

As you can see, it first determines what we have to play with, and then calls a function to consume it. The second parameter to ConsumeMemory allows you to specify the speed which it consumes memory. If you set this to 1 then the usage will be slow; however, if you set it higher than you want for the remaining memory then it may use too much. Also, it doesn’t seem to improve speed much after that anyway.

The ConsumeMemory() function looks like this:

        static void ConsumeMemory(long memoryToConsumeMB, int consumePerItt)
        {            
            long bitsPerMB = 1024 * 1024 * 8;
            // Single char 2 bytes (16 bits)
            long numCharsPerMB = (bitsPerMB / 16);
            long numChars = numCharsPerMB * memoryToConsumeMB;
            long counter = 1, chunk = 0;

            if (memoryToConsumeMB > GetRemainingMemory())
            {
                Console.WriteLine("Cannot consume {0} because there is only {1} left", 
                    memoryToConsumeMB, GetRemainingMemory());
            }

            counter = memoryToConsumeMB / consumePerItt;
            chunk = numCharsPerMB * consumePerItt;

            Console.WriteLine("Consuming {0} memory", memoryToConsumeMB);

            for (int i = 1; i <= counter; i++)
            {
                Console.WriteLine("Consuming {0} MB", chunk / numCharsPerMB);

                _str.Add(new string('_', (int)chunk));

                Console.WriteLine("Memory remaining: {0}", GetRemainingMemory());
            }
        }

So, we basically work out how much memory we’re using each iteration and just add to a list of strings each time. Here’s what it looks like when you run it as above:

Chaos1

The FreeMemory() function just releases the list and calls the GC:

        private static void FreeMemory()
        {
            _str = null;
            GC.Collect();
            ShowMemory();
        }

As you can see, it ramps up pretty quick. In this case I’m leaving 2GB.

Super Chaos Monkey Mode

Let’s try putting this in a loop and take out the prompts:

        static void Main(string[] args)
        {
            long remainingMemory = int.Parse(args[0]);

            while (true)
            {
                // Determine how much memory there is
                long memoryLeft = GetRemainingMemory();
                Console.WriteLine("Consuming memory until {0} is left", remainingMemory);

                // Calculate how much memory to use
                long removeMemory = memoryLeft - remainingMemory;

                // Call the function to consume the memory
                Console.WriteLine("Consuming {0} memory", removeMemory);
                ConsumeMemory(removeMemory, 1000);

                // Free the memory
                Console.WriteLine("Press any key to free memory");
                //Console.ReadLine();
                FreeMemory();
            }

            //Console.ReadLine();
        }

        private static void FreeMemory()
        {
            _str = new List<string>();
            GC.Collect();
            ShowMemory();
        }

Chaos2

A note on the GC

Okay – there are very few cases where the GC.Collect() should be called. But I believe this to be one of them. The reason being that, not calling it explicitly ends in the following:

Chaos3

Basically, by the time the garbage collection kicks in, you’re already allocating more memory, which affects the ebb and flow.

Super speed chaos

If you want very rapid consumption of memory, just alter the consume memory function as follows:

            //for (int i = 1; i <= counter; i++)
            Parallel.For(1, counter + 1, (i) =>
              {
                  Console.WriteLine("Consuming {0} MB", chunk / numCharsPerMB);

                  _str.Add(new string('_', (int)chunk));

                  Console.WriteLine("Memory remaining: {0}", GetRemainingMemory());
              });

Chaos4

Be very careful with this one, though. A slight bug in your code and you’ll need to do a hard reboot of your machine.

Chaos Monkey – Part 2 – Programmatically Resetting IIS at Scheduled Intervals

In this previous post I gave an example of a DOS batch script that simulated an unstable network. This is an alternative to that in .NET, which uses the `System.ServiceProcess` namespace

Let’s start with the main function:

        private static async Task MainLoop()
        {
            while (true)
            {
                Console.WriteLine("Stopping IIS");
                StopService("World Wide Web Publishing Service", 10000);

                await Task.Delay(3000);

                Console.WriteLine("Starting IIS");
                StartService("World Wide Web Publishing Service", 10000);

                await Task.Delay(5000);
            }
        }

This defines the flow of the code: essentially, it’s just stop the IIS service, wait, start it again… and wait. The service name for IIS is “World Wide Web Publishing Service” – at least for Windows 7 & 8 it is. The start and stop functions look like this:

        public static void StartService(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);

            TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

            service.Start();
            service.WaitForStatus(ServiceControllerStatus.Running, timeout);
        }

        public static void StopService(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);

            // Only stop if it's started
            if (service.Status != ServiceControllerStatus.Running) return;

            TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

            service.Stop();
            service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
        }

Obviously these could be used to stop and start any service; although you must be running as admin to affect admin services (such as IIS).

To test this, check you have a “default.htm” in your wwwroot and then navigate to localhost in a web browser. Run this app in the background and press F5 on your browser until you get an error.

Chaos Monkey – Part 1 – Simulating a dodgy network on a local IIS

I thought I’d share this little DOS script that I’ve been using to simulate an unstable network connection on a local IIS:

:startLoop
	iisreset
	ping 1.1.1.1 -n 1 -w 10000 > nul
	GOTO startLoop
:endLoop

Not rocket science, but it does what it says on the tin. I saved it into a batch file and run that along with my app.