Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the Task Parallel Library have a 'hidden' 1 second timeout for scheduling tasks under certain conditions?

My laptop has 2 logical processors and I stumbled upon the scenario where if I schedule 2 tasks that take longer than 1 second without designating them long-running, subsequent tasks are started after 1 second has elapsed. It is possible to change this timeout?

I know normal tasks should be short-running - much shorter than a second if possible - I'm just wondering I am seeing hard-coded TPL behavior or if I can influence this behavior in any way other than designating tasks long-running.

This Console app method should demonstrate the behavior for a machine with any number of processors:

static void Main(string[] args)
{
    var timer = new Stopwatch();
    timer.Start();

    int numberOfTasks = Environment.ProcessorCount;

    var rudeTasks = new List<Task>();
    var shortTasks = new List<Task>();

    for (int index = 0; index < numberOfTasks; index++)
    {
        int capturedIndex = index;
        rudeTasks.Add(Task.Factory.StartNew(() =>
        {
            Console.WriteLine("Starting rude task {0} at {1}ms", capturedIndex, timer.ElapsedMilliseconds);
            Thread.Sleep(5000);
        }));
    }

    for (int index = 0; index < numberOfTasks; index++)
    {
        int capturedIndex = index;
        shortTasks.Add(Task.Factory.StartNew(() =>
        {
            Console.WriteLine("Short-running task {0} running at {1}ms", capturedIndex, timer.ElapsedMilliseconds);
        }));
    }

    Task.WaitAll(shortTasks.ToArray());
    Console.WriteLine("Finished waiting for short tasks at {0}ms", timer.ElapsedMilliseconds);

    Task.WaitAll(rudeTasks.ToArray());
    Console.WriteLine("Finished waiting for rude tasks at {0}ms", timer.ElapsedMilliseconds);

    Console.ReadLine();
}

Here is the app's output on my 2 proc laptop:

Starting rude task 0 at 2ms
Starting rude task 1 at 2ms
Short-running task 0 running at 1002ms
Short-running task 1 running at 1002ms
Finished waiting for short tasks at 1002ms
Finished waiting for rude tasks at 5004ms

Press any key to continue . . .

The lines:

Short-running task 0 running at 1002ms
Short-running task 1 running at 1002ms

indicate that there is a 1 second timeout or something of that nature allowing the shorter-running tasks to get scheduled over the 'rude' tasks. That's what I'm inquiring about.

like image 613
ZeroBugBounce Avatar asked Jan 18 '23 08:01

ZeroBugBounce


1 Answers

The behavior that you are seeing is not specific to the TPL, it's specific to the TPL's default scheduler. The scheduler is attempting to increase the number of threads so that those two that are running don't "hog" the CPU and choke out the others. It's also helpful in avoiding deadlock situations if the two that are running start and wait on Tasks themselves.

If you want to change the scheduling behavior, you might want to look into implementing your own TaskScheduler.

like image 63
Chris Shain Avatar answered Feb 03 '23 21:02

Chris Shain