For a number of upcoming projects (make sure to follow/like on Facebook and other social media to stay up to date of when I release them), I needed to create high performance, low impact .NET code which was able to scan a large range of IP addresses and ports in the quickest amount of time possible.

So naturally, I performed some tests to see the outcome of each of the patterns, using them in a normal way and using them in a number of different combinations to try and squeeze as much as possible out of them.

The patterns that I am going to base the tests on are the following:

  • Task Parallel Library (TPL) is designed to make developers more productive by making it easier to add parallelism and concurrency to applications TPL scales dynamically to make use of all processors that are available. Using TPL allows you to focus more on the application's core functionality.
  • Task-based Async Pattern (TAP) allows for a single method to represent the initiation and completion of an asynchronous operation.
  • Async Programming Model (APM) uses the IAsyncResult design pattern, which is implemented using two methods named BeginMethodName and EndMethodName that are used to begin and end asynchronous operations respectively.
  • Event-based Async Pattern (EAP) allows easy implementation of "in the background" operations, without interrupting the application. (this has been replaced by TAP completely and will not be tested as the Async method of the TCP client uses TAP)


The following test were performed using port 80 for 255 unique IP Addresses using the following machine specs:

First Machine: Dual-Core CPU & 4 GB RAM

Second Machine: Octa-Core CPU & 14 GB RAM

Solution

TCP Client Type & Notes

Seconds taken on 1st machine

Seconds taken on 2nd machine

Normal (Control Test)

APM

129.57

134.38

*

TAP

130.48

131.42

Task-Based Only

Task Based Loop with TAP

131.33

130.27

Task-Based Run Loop

APM

10.13

7.39

*

TAP

6.26

7.62

*

Mix and Mash with 4 pre task runners and multiple sub task runners with TAP

8.07

6.32

Parallel For Each Loop

Max Degree of parallelism set to default and with APM

22.58

16.03

*

Max Degree of parallelism set to default and with TAP

16.20

15.30

*

Max Degree of parallelism set to 999 and with APM

8.6

7.11

*

Max Degree of parallelism set to 999 and with TAP

8.7

7.16


Looking at the results above, it seems that they are all relative to each other in the terms of time it takes for each test to execute. The only visible difference seems to be with the amount of cores used, the more cores used, the less time it takes.

Depending on the scenario, it would be ideal to either use TPL or TAP to implement parallel or asynchronous code as recommended by .NET best practices and avoid the use of legacy APM or EAP as they will be phased out over time.

I have uploaded the test application source to GitHub and is being released as GNU GPL, so go grab a copy and perform the tests on your machine from here if you wish: https://github.com/lookuga/CodeTests