maximize your .net application performance task parallel library - tpl
DESCRIPTION
Maximize Your .NET Application Performance Task Parallel Library - TPL. 25th September 2014 b y Romulus Susanu. Topics. Parallel Processing and Concurrency Synchronous vs Asynchronous Asynchronous Programming Patterns in .NET Task Parallel Library - TPL Data Parallelism Task Parallelism. - PowerPoint PPT PresentationTRANSCRIPT
Maximize Your .NET Application Performance
Task Parallel Library - TPL
25th September 2014by Romulus Susanu
Topics• Parallel Processing and Concurrency
• Synchronous vs Asynchronous
• Asynchronous Programming Patterns in .NET
• Task Parallel Library - TPL Data Parallelism Task Parallelism
Parallel Processing and Concurrency
• keep your application responsive
• maximize the performance of your code
Parallel Processing vs Concurrency
Parallelism • refers to techniques to make programs faster by performing several
computation in parallel.
• requires hardware with multiple CPU
Key problem • reduce data dependencies
Parallel Processing vs Concurrency
Concurrency• refers to techniques that make program more usable
• can be implemented and is used a lot on single CPU
• multi-tasking operating system is synonym for supporting concurrency
Parallel Processing vs Concurrency
Synchronous vs Asynchronous
• in .NET it's directly related with threads
• in a threaded system the decision to suspend one thread and execute another
is largely outside of the programmer’s control
• threaded model execution are handled by the OS
Synchronous vs Asynchronous
Synchronous • wait for it to finish before moving on to another task
Asynchronous • move on to another task before it finished
• executing a process/task on another thread
Why asynchronous programming is more performing?
Synchronous vs Asynchronous
Why asynchronous programming is more performing?
Blocking in a synchronous program The asynchronous model
Why would a task be blocked?
Synchronous vs Asynchronous
Why would a task be blocked?• waiting to perform I/O
• to transfer data to or from an external device.
An asynchronous program is often called a non-blocking program!
Synchronous vs Asynchronous
When the asynchronous model performs best?
• there are a large number of tasks so there is likely always at least one task that can make progress.
• the tasks perform lots of I/O, causing a synchronous program to waste lots of time blocking when other tasks could be running.
• a network server implementation is a prime candidate for the asynchronous model
Every time the OS transfers control over from one thread to another it has to save all the relevant registers, memory map, stack pointers, FPU context etc. so that the other thread can resume execution where it left off.
Asynchronous Programming Patterns in .NET
• Asynchronous Programming Model (APM) (also called IAsyncResult Pattern)
• Event-based Asynchronous Pattern (EAP)
• Task-based Asynchronous Pattern (TAP)
Asynchronous Programming Patterns in .NET
Asynchronous Programming Model (APM)• asynchronous operations require Begin and End methods
• no longer recommended for new development
Asynchronous Programming Patterns in .NET
Asynchronous Programming Model (APM)
Code sample:
• consider a Read method that reads a specified amount of data into a provided buffer starting at a specified offset
public class MyClass{ public IAsyncResult BeginRead(byte [] buffer, int offset, int count, AsyncCallback callback, object state);
public int EndRead(IAsyncResult asyncResult);}
Asynchronous Programming Patterns in .NET
Event-based Asynchronous Pattern (EAP)• requires a method that has the Async suffix and one or more events
• was introduced in the .NET Framework 2.0
• no longer recommended for new development
Asynchronous Programming Patterns in .NET
Event-based Asynchronous Pattern (EAP)Code sample:
public class AsyncExample{ // Synchronous methods. public int Method1(string param); // Asynchronous methods. public void Method1Async(string param); public event Method1CompletedEventHandler Method1Completed; public void CancelAsync(); public bool IsBusy { get; } }
BackgroundWorker components represent more complex implementations of EAP (RunWorkerAsync(), CancelAsync, ProgressChanged, RunWorkerCompleted etc.)
Asynchronous Programming Patterns in .NET
Task-based Asynchronous Pattern (TAP)• uses a single method to represent the initiation and completion of an
asynchronous operation
• was introduced in the .NET Framework 4.0
• recommended approach to asynchronous programming
Asynchronous Programming Patterns in .NET
Task-based Asynchronous Pattern (TAP)
Code sample:public class MyClass
{ public Task<int> ReadAsync(byte [] buffer, int offset, int count);}
System.Threading.Tasks Namespace
• provides types that simplify the work of writing concurrent and asynchronous code
Task Parallel Library - TPL
Data Parallelism
Task Parallelism
Task Parallel Library - TPL
Data Parallelism• refers to scenarios in which the same operation is performed concurrently
• the source collection is partitioned so that multiple threads can operate on different segments concurrently
• data parallelism through the System.Threading.Tasks.Parallel class
• Parallel class provides method-based parallel implementations of for and foreach loops
Task Parallel Library - TPL
Data Parallelism
The SumRootN method returns the sum of the nth root of all integers from one to 10 million, where n is a parameter
Sequential loop
for(int i=2;i<20;i++){
var result=SumRootN(i);Console.WriteLine("root{0}:{1}",i,result);
}
public static double SumRootN(int root){
double result=0;for(int i=1;i<10000000;i++){
result +=Math.Exp(Math.Log(i)/root);}Return result;
}
Task Parallel Library - TPL
Data Parallelism
// For loops
// Method signature: Parallel.For(int fromInclusive, int toExclusive, Action<int> body)
Parallel.For(2,20,(i)=>{
var result=SumRootN(i);Console.WriteLine("root{0}:{1}",i,result);
});
// ForEach loops
var roots = new List<int> { 2, 3, 4, …,20};
// Method signature: Parallel.ForEach(IEnumerable<TSource> source, Action<TSource> body)
Parallel.ForEach(roots,(i)=>{
var result = SumRootN(roots[i]);Console.WriteLine("root{0}:{1}",i,result);
});
Task Parallel Library - TPL
Task Parallelism• a task represents an asynchronous operation
• in some ways it resembles the creation of a new thread or ThreadPool work item
// Define and run the task.Task taskA = Task.Run( () => Console.WriteLine("Hello from taskA."));
Task Parallel Library - TPL
Task Parallelism
Tasks provide two primary benefits:
• more efficient and more scalable use of system resources
lock-free algorithm - ConcurrentQueue<T>
Hill Climbing algorithm
Work-Stealing algorithm
• more programmatic control than is possible with a thread or ThreadPool work item
Task Parallel Library - TPL
Hill Climbing algorithm
• to improve the utilization of cores when threads are blocked by I/O or other wait conditions that stall the processor
• the .NET thread pool has an opportunity to inject threads every time a work item completes or at 500 millisecond intervals, whichever is shorter
• if adding threads seems to be helping throughput, the thread pool adds more; otherwise, it reduces the number of worker threads.
Task Parallel Library - TPL
Work-stealing algorithms
ThreadPool Global Queue vs. Local Queues
Extra efficiencies:
• improved cache locality
• minimized contention
Task Parallel Library - TPL
Work-stealing algorithms
What happens when a thread's local work queue is empty and the global queue is also
empty?
Benefits:
• Load-balancing
Task Parallel Library - TPL
TPL - More programmatic control
Creating and Running Tasks Implicitly
• just pass in an Action delegate for each item of work
Parallel.Invoke(() => DoSomeWork(), () => DoSomeOtherWork());
Task Parallel Library – TPLTPL - More programmatic control
Creating and Running Tasks Explicitly• a task that does not return a value is represented by the System.Threading.Tasks.Task
class
• the Task.Wait method to ensure that the task completes execution before the console mode application ends
Thread.CurrentThread.Name = "Main";
// Create a task and supply a user delegate by using a lambda expression. Task taskA = new Task( () => Console.WriteLine("Hello from taskA.")); // Start the task. taskA.Start();
// Output a message from the calling thread. Console.WriteLine("Hello from thread '{0}'.", Thread.CurrentThread.Name);
taskA.Wait();
// The example displays the following output: // Hello from thread 'Main'. // Hello from taskA.
Task Parallel Library – TPLTPL - More programmatic control
Creating and Running Tasks Explicitly
Task.Run method• the Run methods use the default task scheduler
• The Run methods are the preferred way to create and start tasks when more control over the creation and scheduling of the task is not needed
Thread.CurrentThread.Name = "Main";
// Define and run the task. Task taskA = Task.Run( () => Console.WriteLine("Hello from taskA."));
// Output a message from the calling thread. Console.WriteLine("Hello from thread '{0}'.", Thread.CurrentThread.Name);taskA.Wait();
// The example displays the following output: // Hello from thread 'Main'. // Hello from taskA.
Task Parallel Library – TPLTPL - More programmatic control
Creating and Running Tasks Explicitly
TaskFactory.StartNew method
Use this method when:
• creation and scheduling do not have to be separated
• require additional task creation options
• use of a specific scheduler Thread.CurrentThread.Name = "Main";
// Better: Create and start the task in one operation. Task taskA = Task.Factory.StartNew(() => Console.WriteLine("Hello from taskA."));
// Output a message from the calling thread. Console.WriteLine("Hello from thread '{0}'.", Thread.CurrentThread.Name); taskA.Wait();
// The example displays the following output: // Hello from thread 'Main'. // Hello from taskA.
Task Parallel Library – TPLTPL - More programmatic control
Creating and Running Tasks Explicitly
System.Threading.Tasks.Task<TResult> classTask<Double>[] taskArray = { Task<Double>.Factory.StartNew(() => DoComputation(1.0)), Task<Double>.Factory.StartNew(() => DoComputation(100.0)), Task<Double>.Factory.StartNew(() => DoComputation(1000.0)) };
var results = new Double[taskArray.Length]; Double sum = 0;
for (int i = 0; i < taskArray.Length; i++) { results[i] = taskArray[i].Result; Console.Write("{0:N1} {1}", results[i], i == taskArray.Length - 1 ? "= " : "+ "); sum += results[i]; }
Console.WriteLine("{0:N1}", sum); }
// The example displays the following output: // 606.0 + 10,605.0 + 100,495.0 = 111,706.0
private static Double DoComputation(Double start) { Double sum = 0; for (var value = start; value <= start + 10; value += .1) sum += value; return sum; }
Task Parallel Library – TPLTPL - More programmatic control
Continuation Tasks• in asynchronous programming, it is very common for one asynchronous operation, on
completion, to invoke a second operation and pass data to it
// The antecedent task. Can also be created with Task.Factory.StartNew. Task<DayOfWeek> taskA = new Task<DayOfWeek>(() => DateTime.Today.DayOfWeek);
// The continuation. Its delegate takes the antecedent task // as an argument and can return a different type. Task<string> continuation = taskA.ContinueWith(
(antecedent) => { return String.Format("Today is {0}.", antecedent.Result); });
// Start the antecedent. taskA.Start();
// Use the contuation's result. Console.WriteLine(continuation.Result);
Task Parallel Library – TPLTPL - More programmatic control
Task Creation Options
TaskCreationOptions parameter value Description
None The default when no option is specified. The scheduler uses its default heuristics to schedule the task.
PreferFairness Specifies that the task should be scheduled so that tasks created sooner will be more likely to be executed sooner, and tasks created later will be more likely to execute later.
LongRunning Specifies that the task represents a long-running operation.
AttachedToParent Specifies that a task should be created as an attached child of the current task, if one exists. For more information, see Attached and Detached Child Tasks.
DenyChildAttach Specifies that if an inner task specifies the AttachedToParent option, that task will not become an attached child task.
HideSchedulerSpecifies that the task scheduler for tasks created by calling methods like TaskFactory.StartNew or Task<TResult>.ContinueWith from within a particular task is the default scheduler instead of the scheduler on which this task is running.
var task3 = new Task(() => MyLongRunningMethod(), TaskCreationOptions.LongRunning);
task3.Start();
Task Parallel Library – TPLTPL - More programmatic control
Continuation Tasks• in asynchronous programming, it is very common for one asynchronous operation, on
completion, to invoke a second operation and pass data to it
// The antecedent task. Can also be created with Task.Factory.StartNew. Task<DayOfWeek> taskA = new Task<DayOfWeek>(() => DateTime.Today.DayOfWeek);
// The continuation. Its delegate takes the antecedent task // as an argument and can return a different type. Task<string> continuation = taskA.ContinueWith(
(antecedent) => { return String.Format("Today is {0}.", antecedent.Result); });
// Start the antecedent. taskA.Start();
// Use the contuation's result. Console.WriteLine(continuation.Result);
Task Schedulers• makes sure that the work of a task is eventually executed
• the default task scheduler is based on the .NET Framework 4 ThreadPool
Custom Task Schedulers
ParallelExtensionsExtras package
• LimitedConcurrencyLevelTaskScheduler - limits the number of threads used by the application
• OrderedTaskScheduler - guarantees that tasks are processed in the order that they were scheduled.
• ThreadPerTaskScheduler - dedicates a thread to each individual task
Task Parallel Library – TPLTPL - More programmatic control
Task Parallel Library – TPLTPL - More programmatic control
Real Case
foreach (SurveyDetail surveyDetail in surveyDetailList){ soFar++; SurveyProcessing.PopulateUPSInformation(surveyDetail);}
private static readonly LimitedConcurrencyLevelTaskScheduler _lcts = new LimitedConcurrencyLevelTaskScheduler(50);
…
IList<Task> tasks = new List<Task>(); var taskFactory = new TaskFactory(_lcts);
foreach (SurveyDetail surveyDetail in surveyDetailList) { var verifyByUpsTask = taskFactory.StartNew( () => PopulateUPSInformation(surveyDetail));}
<connectionManagement> <add address="*" maxconnection="48" /> </connectionManagement>
webconfig
Thank you!