Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cpu usage increasing up to 100% in infinite loop in thread

I am implementing a web based chat platform in ASP.NET Web Application, and I use technique similar to long polling. I mean I keep each web request from client for a specific time period(timeout) or until new message arrives, and then response is sent to the client.

I keep connected clients in memory(dictionary object) and when ever new message is sent to a client, I write this message into receiver client's messages array. Client needs to send a request to get his own messages, and I keep this request in an array in memory.

I am using asynchronous http handler for listenings client request, I am keeping web requests in an array in memory. I use threads to check for new messages continously from memory (in dictionary which is created for each client).

I do not use .net thread pool threads to check for new messages or timed out web requests.I create threads like this:

System.Threading.Thread t = new Thread(new ThreadStart(QueueCometWaitRequest_WaitCallback));
t.IsBackground = false;
t.Start();

In each thread's QueueCometWaitRequest_WaitCallback method I am in an infinite while loop:

while (true)
{
...
Thread.Sleep(100);
}

In this method, I am checking for web request time out or new message for each Web Request which is also kept in an array in memory.

Everything was working good until I noticed that CPU usage is reaching up to 100% in time. (in minutes after the first connected client) At the beginning of first request everything seems to be normal, I mean the CPU usage is not higher than 10% while returning a response to the client. But in time even with 2 clients the CPU usage is increasing up to 100%. It seems CPU usage is 100% only when writing to a response for a client request. If no client is left then everything return to a normal (CPU usage is about 0%) until new web request is done by a client.

I don't know the threads in detail, but I am suspicious about the new threads which I created and works infinitely. It is like operating system gives them more CPU usage and resource in time since they are working all the time, and this Thread.Sleep(100) is not working.

Here is the QueueCometWaitRequest_WaitCallback() method:

void QueueCometWaitRequest_WaitCallback()
{
   while (true)
   {
      if (processRequest.Length == 0)
      {
          Thread.Sleep(100);
      }
      else
      {
          for (int i = 0; i < processRequest.Length; i++)
          {
               Thread.Sleep(100);

               // below I am checking for new message or request time out 
               .................
               .................

               // If new message or time out I write to response
          }
      }    
   }
}

I hope I could explain the situation, and I am open to any suggestion as well (like implementing in a different way)

If you can help me with this problem I will appreciate gratefully, Thanks

like image 609
Mehmet Avatar asked Jan 16 '12 14:01

Mehmet


People also ask

What happens if CPU goes over 100%?

If the CPU usage is around 100%, this means that your computer is trying to do more work than it has the capacity for. This is usually OK, but it means that programs may slow down a little. Computers tend to use close to 100% of the CPU when they are doing computationally-intensive things like running games.

How do you stop an infinite loop in a thread?

The only way to stop a thread asynchronously is the stop() method.

How do I reduce CPU thread usage?

The best solution to limiting the cpu usage for a process or thread is to make sure that the thread or process uses less cpu. That can best be done by improving the efficiency of the code, or by calling it less often. The aim is to make sure that the process doesn't continually consume all of its available time slice.

Why is my CPU usage constantly so high?

You can expect high CPU utilization when playing some games, running a video-editing or streaming application, performing an antivirus scan, or juggling many browser tabs.


1 Answers

Just as a general best-practices comment as opposed to direct answer - it's not advisbable to write a Thread.Sleep(100) inside your message receiver thread. A better method would be to use Thread.Join as previously mentioned or ManualResetEvent wait handles. For instance, you could code like this:

private ManualResetEvent waitHandle;
private object syncRoot = new object();
private bool isRunning = false;

void CreateThread()
{
    this.waitHandle = new ManualResetEvent(false);

    isRunning = true; // Set to false to kill the thread
    System.Threading.Thread t = new Thread(new ThreadStart(QueueCometWaitRequest_WaitCallback));         
    t.IsBackground = false; 
    t.Start();
}

void PushData()
{
    // On incoming data, push data into the processRequest queue and set the waithandle
    lock(syncRoot)
    {
        processRequest.Add(/* ... your data object to process. Assumes this is a queue */);
        waitHandle.Set(); // Signal to the thread there is data to process
    }
}

void QueueCometWaitRequest_WaitCallback() 
{    
    while (isRunning)    
    {       
        // Waits here using 0% CPU until the waitHandle.Set is called above
        this.waitHandle.WaitOne();

        // Ensures no-one sets waithandle while data is being processed and
        // subsequently reset
        lock(syncRoot)
        {
            for (int i = 0; i < processRequest.Length; i++)           
            {                        
                // Process the message. 
                // What's the type of processRequest? Im assuming a queue or something     
            }       

            // Reset the Waithandle for the next requestto process
            this.waitHandle.Reset();
        }
    }        
} 

This would ensure that your thread uses 0% CPU while waiting and only consumes CPU when there is work to do.

Failing that have you thought about a third party solution to asynchronous bi-directional messaging? I have used RabbitMQ (AMQP) with great success in .NET applications to handle high throughput messaging. The API for RabbitMQ means you get an event back when a message has been received which can then be processed on a background thread.

Best regards,

like image 117
Dr. Andrew Burnett-Thompson Avatar answered Oct 03 '22 02:10

Dr. Andrew Burnett-Thompson