ThreadPool.QueueUserWorkItem memory problem


B

Brian Stoop

Hi,

When I run the simple Console application below, the memory keeps climbing.
Is there a way to use the ThreadPool and avoid this memory problem ?


thanks, Brian




using System;
using System.Text;
using System.Threading;

namespace Abc
{
class Program
{
static void Main(string[] args)
{
for (int i=0; i>=0; i++)
{
Thread.Sleep(0);
ThreadPool.QueueUserWorkItem(new WaitCallback(sayHello));
}
}

public static void sayHello(Object o)
{
Console.WriteLine("hello");
}
}
}
 
Ad

Advertisements

P

Pavel Minaev

Hi,

When I run the simple Console application below, the memory keeps climbing.
Is there a way to use the ThreadPool and avoid this memory problem ?

thanks, Brian

using System;
using System.Text;
using System.Threading;

namespace Abc
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i=0; i>=0; i++)
            {
                Thread.Sleep(0);
                ThreadPool.QueueUserWorkItem(new WaitCallback(sayHello));
            }
        }

        public static void sayHello(Object o)
        {
            Console.WriteLine("hello");
        }
    }
}

Well, of course it will keep climbing - your worker thread method is
simply more expensive than a single iteration of your loop, so you add
work items to the queue faster than they get executed. Thus the queue
grows, consuming memory.

If your actual production code does the same thing, then you have to
understand that it's not really a ThreadPool problem - it's a more
fundamental problem either with your design, or your workload. It
boils down to this: if you have more work requests than you can serve
_and_ queue, then you have to start refusing some of them eventually.
If you just keep spawning threads, then you'll run into OS limit on
their amount (though the system will probably slow down to a crawl
even before that); if you keep extending the queue, you'll consume all
available memory eventually. At some point, you _have_ to start
saying, "sorry, this can't be done".

So the generic answer is: keep track of how many work items you have
in the queue, and start dropping any new incoming ones when there are
too many; preferably making the specific number end-user configurable.
 
A

Ajay

You are much more likely to be able to achieve the first goal than the  
second.  Queuing a work item is a very quick operation.

I am curious if sayHello was empty({}), can the same problem still
show up? Is there any overhead for just starting/finishing the
threadpool thread, which is more than queuing?

Just wondering.
 
B

Brian Stoop

Thanks for all your help,

I change to ThreadSleep(2) and the memory sits at 15K.


Brian
 
W

william.w.oneill

Once the pool has stabilized, the thread pool has a better chance of  
catching up, but in fact I don't believe it will.  The creation of  
thousands of threads would, in this case, wind up being  
counter-productive, because instead of allowing the same thread to just  
keep processing work items as fast as it can, you'll wind up with  
thousands of threads contending for the CPU at the same time.  The context  
switching will dominate the CPU cost, with very little CPU time spent  
doing "real" work (such as there would be in this degenerate example :) )..

Hi Pete,

Isn't the default maximum number of thread per core 25? I don't see
how the original poster's code will create thousands of threads.

I ask because I've relied on this documented behavior in the past. If
it behaves differently, I would really like to know.

Thanks,
Bill
 
A

Ajay

Isn't the default maximum number of thread per core 25?

As per the 3.5 docs, this appears to be true:

http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

<>
The number of operations that can be queued to the thread pool is
limited only by available memory; however, the thread pool limits the
number of threads that can be active in the process simultaneously. By
default, the limit is 25 worker threads per CPU and 1,000 I/O
completion threads.

You can control the maximum number of threads by using the
GetMaxThreads and SetMaxThreads methods.
</>
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top