1

I need to handle http requests and the best way I found was using a ThreadPool. Please dont recommend using a finished library, because when I try to do something similar, there will be the same problem(s)!

When try a DDOS-Tool on my own webserver the cpu usage gets high and the memory increases incredible fast!

When I stop the tool the memory usage still increases (see screenshot)!

I want the program to decrease its memory usage after the DDOS-Tool has been stopped.

But unfortunately it does not!

Here is my code: You can try it. It does not need any libraries!

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Threading;

namespace Webserver
{
  class Program
  {
    static void Main(string[] args)
    {
      TcpListener tcpListener = new TcpListener(81);
      tcpListener.Start();
      while (true)
        ThreadPool.QueueUserWorkItem(DoWork, tcpListener.AcceptTcpClient());
    }

    static void DoWork(object arg)
    {
      try
      {
        using (TcpClient tcpClient = (TcpClient)arg)
        {
          tcpClient.ReceiveTimeout = 500;
          tcpClient.SendTimeout = 500;

          using (NetworkStream networkStream = tcpClient.GetStream())
          {
            networkStream.ReadTimeout = 500;
            networkStream.WriteTimeout = 500;

            List<string> headers = new List<string>();

            using (StreamReader streamReader = new StreamReader(networkStream))
            using (StreamWriter streamWriter = new StreamWriter(networkStream))
            {
              while (true)
              {
                string line = streamReader.ReadLine();

                if (line == "") break;
                else headers.Add(line);
              }

              Console.WriteLine(headers[0]);

              streamWriter.WriteLine("HTTP/1.0 200 OK");
              streamWriter.WriteLine("Server: Webserver");
              streamWriter.WriteLine("Content-Type: text/html; charset=UTF-8");
              streamWriter.WriteLine("");
              streamWriter.WriteLine("Hello World!");
            }
          }
        }
      }
      catch (Exception ex)
      {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine(ex.Message);
        Console.ResetColor();
      }
    }
  }
}

Screenshot of Process Hacker's statistcs

The red lines mark the timestamps when I started and stopped the ddos-Tool. As you can see, the memory still increases after the tool has been stopped.

I want my program to get down back to 17 MB memory usage as it was at the beginning.

feedc0de
  • 3,646
  • 8
  • 30
  • 55
  • 3
    Does it need to? Because if not - it will not. The GC is not "clean it all up". It is "clean up if needed". Also your DDOS tool likely issued a ton of requests THAT ARE STILL IN THE QUEUE WHEN IT STOPS. – TomTom Dec 02 '14 at 15:05
  • But when I stop my tool (means killing it from task manager) all opened requests will fail instantly when the DoWork() starts. I can see those messages in my console. Those error message keep showing some seconds after i stopped the tool (but not forever) – feedc0de Dec 02 '14 at 15:07
  • 1
    @DanielBrunner No, they *won't* die right away. They'll eventually time out and die *after some period of time*. – Servy Dec 02 '14 at 15:13
  • 4
    You are just seeing the effect of a heuristic in the GC, it allocates bigger segments when the app consumes a lot of memory. It takes time to learn that the app is slowing down again, collections don't happen very often when the app goes idle. So you just didn't wait long enough. All rather irrelevant to *real* memory usage, you are looking a virtual memory statistic. Just numbers to the processor, one for each 4096 byte allocation. Nothing to do with RAM. This is a feature, not a problem. – Hans Passant Dec 02 '14 at 16:46

1 Answers1

-1

This similar question has some good advice.

Your code is currently already pretty efficient as it is. The using statements automatically disposes the objects when finished so you don´t need to worry about them. As for using garbage collection anywhere is always a tricky business especially in a multy threading environment.

To use the garbage collection just type:

// for a full garbage collection:
GC.Collect();
// for a first generation garbage collection:
GC.Collect(0);

this forces the Garbage collector to 'Collect' the garbage. Garbage collection is thread safe and it blocks all other threads. Since other threads are blocked it might result in some latency. I'm not sure if it will improve your performance, but by all means try.

For more information on how it works you can read this article

Community
  • 1
  • 1
martijn
  • 1,417
  • 1
  • 16
  • 26
  • I will try that. Is it okay to have a Timer that does this job? Or should I do it after a amount of requests (lets say after 1000 requests)? – feedc0de Dec 03 '14 at 08:01
  • I would suggest a little experimentation on your behalf. Try both and see which one has the better outcome, and try other combinations as well. I would also use a trial without forced garbage collection as a control experiment and a trial with garbage collection after the DDOS. – martijn Dec 03 '14 at 09:40