January 5, 2012 8:37pm
Random F# Knowledge gained today

Today I started going through the tutorial for F# on www.tryfsharp.org. So far this tutorial is excellent and lets you quickly try F#. The site uses a silverlight plugin which allows you to run F# code in your browser without any IDE. You are up and running within seconds. So far I managed to go through the first section which covers the basics of F#. I will admit some of the constructs so far are nice, not needing to use type annotations because of type inference and the clean syntax of the language (not needing {}, ;, etc). The only complaint so far in the tutorial is with the variable names, they are short and hard to wrap my head around (especially in the currying examples). Anyways here are some random notes I took while going through the first section. Some of this stuff is sort of basic, however typing it up will hopefully make it stick.

  • let statements are not assignment statements. Each let statement creates a new association between a name and a value. In functional programming, such an association is called a binding.
  • In F# indentation matters when writing code there is no termination character such as a ; to terminate a line.  Also there is no {} characters used if/else blocks as in C#.
    C#
    if(x < 5){
        Console.WriteLine("< 5");
    }
    
    F#
    if x < 5
         printfn "< 5"
    
  • There is no void return type in F#, instead the return type would be unit.
  • tuple

    A tuple is similar to a struct in C#, you can define them with any number of named values, however they should be kept fairly small. You can access the values of a tuple by either fst (first value of a tuple) or snd (second value of a tuple)
    let computer = ("iMac", "i7")
    let name = fst computer
    let cpu =  snd computer
    
    Where name contains “iMac” and cpu contains “i7”
  • tuples can not be modified, if you need to alter the values contained in a tuple you need to create a mutable type.
  • Lists

    Lists must contain the same type of values. Each item in a list is separated by ;
    let languages = ["C#"; "F#"; "JavaScript"]
    
  • You can create lists of number with the the “..” operator. let oneToTen = [1 .. 10] will create a list of numbers 1-10, however if you supply two “..” you can specify the number to increment the value. let plusTen = [1 .. 10 .. 100] (e.g. 1, 11, 21, 31…91)
  • Lists are 0 based and if you need to access an element of a list you simply use the [] syntax, with the previous example let number = plusTen.[3] will bind 31 to number;
  • If you want to add an element to the start of a list use :: let newList = -10 :: plusTen
  • If you need to join two lists together use the “@” operator, let myList = plusTen @ newList, this should be used only when needed since it can be expensive depending on the size of the list. You cannot alter an element inside of the list natively, however you can write a function that would allow this to happen by copying the contents and creating a new list. A list is immutable
  • Operators

    F# has the typical arithmetic operators, boolean operators, and comparison operators. One notable operator that is unique to F# is the compare operator.
    let x = 1
    let y = 2
    let lessThan compare x y //returns -1
    
    let x = 1
    let y = 2
    let lessThan compare y x //returns 1
    
    let x = 1
    let y = 1
    let lessThan compare y x //returns 0
    
  • Implicit type conversations do not happen automatically.
    let sum = 29 + 3.5 // does not compile
    
    If you need to provide an explicit conversion for this addition to occur.
    let sum = float 29 + 3.5 //works
    
  • There are a few built in implicit conversions in F# between types.
    • sbyte converts to a signed byte
    • byte converts to an unsigned byte
    • int16 converts to a 16-bit signed integer
    • uint16 converts to a 16-bit unsigned integer
    • int or int32 converts to a 32 bit signed integer
    • uint or uint32 converts to a 32 bit unsigned integer)
    • int64 converts to a 64 bit signed integer
    • uint64 converts to a 64 bit unsigned integer
    • float converts to a double precision float
    • float32 converts to a single precision float
    • decimal converts to a decimal number
    • string converts to a string
    • char converts to a unicode character
  • F# is a statically typed language, and type mismatches will be uncovered by the compiler.
  • Type annotations are not required in F# like in C#. F# achieves this by using type interference to determine what that actual type is in the application. Because of this type interference it is possible that the compiler might choose the wrong type as a parameter or return value. This especially occurs when dealing with + and * calculations. If you are not sure you can easily add the type names to make sure your method has the proper signature of float instead of the potential inferred type of int.
  • Functions are first class objects and can be passed around and even used a parameters in another functions.
  • Being able to pass functions around is essential for predicates passed into List methods such as exists, filter, map, reduce, fold.
  • F# allows for function currying which allows you to create new functions based upon other functions.
    let add a b = a + b
    let addn n = add n
    let f = addn 7
    // What is printed by the following line of code?
    printfn "Value of f 3 = %A" (f 3)
    
    What happens here is that you call function f with a parameter 3 it calls addn 7, addn then calls add n which then unravels to 3 + 7. I think I follow this, but not sure if I can describe it completely just yet.
  • Namespaces and modules

    To use another namespace in your F# program you use open System (similar to C#’s using System;)

Items accomplished

  • Read wikipedia
  • ordered a book

January 4, 2012 7:11pm
Language for January F# (1/12)

Today I met with our little group that is joining me on the journey on learning twelve programming languages in twelve months in the year 2012. We collectively decided to learn F# as our head first dive into our challenge.

Why F#?

Well to be honest the decision was more out of convenience, we all are .net developers running Visual Studio 2010, have all the frameworks installed, and have the given tools needed to get started with little or no effort. Given we are already in January coming off a holiday this seemed like the logical choice.

What is F#?

I will not go into to much detail about F# since everything you might want to know is located on wikipedia. So far all I know is that F# is a language that supports three major programming styles. F# is functional programming, imperative programming, and object-oriented programming.

The next step

  • Read the wikipedia page
  • Find a good book to start learning F#, maybe this one.
  • Go through the tutorials on www.tryfsharp.org. (run F# in your browser with silverlight)
  • Decide on a project to build.

Until next time…

printfn "Hello World, from my first F# program"

July 16, 2011 4:45pm
iOS4 in Action, Chapter 6 part 2.  IBActions with a button/slider, and how to hide the keyboard.

iOS4 in Action, Chapter 6 part 2.  IBActions with a button/slider, and how to hide the keyboard.

July 7, 2011 7:55pm
Chapter 4-1, Simple Web Browser

Chapter 4-1, Simple Web Browser

January 6, 2011 6:21pm
Three Different ways to Access Data via Enterprise Library

Today we are going to be talking about three different way to access data via enterprise library.  The elusive DataSet (a collection of DataTables), IDataReader/IDataRecord, and Execute[Sproc/SqlString)]Accessor.  First up is DataSet

DataSet

DataSets are quick and easy to pull data from Sql, set the command, execute a method and bam you have your data, all you need to do is index into the rows/columns and you can grab whatever you want.  However working with objects are so much nicer so in our example we are going to map our dataset over to a object.

var command = DataBase.GetSqlStringCommand("SELECT [BookId], [Name], [ISBN] FROM Books");
var dataTable = DataBase.ExecuteDataSet(command).Tables[0];

for (int i = 0; i < dataTable.Rows.Count; i++)
{
    books.Add(new Book
    {
        Id = Convert.ToInt32(dataTable.Rows[i]["BookId"]),
        Name = dataTable.Rows[i]["Name"].ToString(),
        ISBN = Guid.Parse(dataTable.Rows[i]["ISBN"].ToString())
    });   
}

Fairly straight foreword, we get our command, execute the ExecuteDataSet and map it to our book. 

IDataReader/IDataRecord

IDataReader actually streams the data one row at a time until there are no more results left from the query.  Since an IDataRecord does not have much structure except it being one row we will also map this to our book object.

var command = DataBase.GetSqlStringCommand("SELECT [BookId], [Name], [ISBN] FROM Books");
using (var reader = DataBase.ExecuteReader(command))
{
    while (reader.Read())
    {
        books.Add(new Book
        {
            Id = Convert.ToInt32(reader["BookId"]),
            Name = reader["Name"].ToString(),
            ISBN = Guid.Parse(reader["ISBN"].ToString())
        });   
    }
}

Once again nothing earth shattering we use the same method to get our command but next we use ExecuteReader.  Since we know that a IDataReader is streaming our data one record at a time we need to make sure to wrap it in a using block so we can dispose of the connection correctly. 

Incase you are curious a using block is just some syntactical sugar for a try{}finally{}.

Note to use a using block the object must implement IDisposable

In our using block we call into read and as long as more records can be read from the query stream we index into the IDataRecord and grab our data to convert into our book object.  Once there are no more records to read we close down the connection and exit out of the loop and using block.

ExecuteSqlStringAccessor

This is the new way of accessing data inside of Enterprise Library 5.  This method takes out much of the pain of mapping your IDataRecord/DataSet to your object by using a new type called IRowMapper.  An IRowMapper simply is a way to describe how the object should be constructed from your IDataRecord.

IRowMapper<Book> rowMapper = MapBuilder<Book>.MapAllProperties().Map(b => b.Id).ToColumn("BookId").Build();
var books = DataBase.ExecuteSqlStringAccessor("SELECT [BookId], [Name], [ISBN] FROM Books", rowMapper).ToList();

As you can see here we created a IRowMapper<Book> via the helper class MapBuilder<Book>.  By default you can just use MapAllProperties if and only if each property has a corresponding column returned from your result set. As you see from our query we are returning BookId instead of Id.  So for this exception we can call MapAllProperties and then declare our property that says for our object book.Id we need to map it to the returned column BookId.  The last method call will build our IRowMapper that we can use in ExecuteSqlStringAccessor.  ExecuteSqlStringAccessor returns an IEnumerable<Book> so to fully populate our list of books we need to call ToList() which will than enumerate the result set and build or list of books.

So which one to use?

DataSet vs IDataReader?  A dataset is disconnected in nature and you can easily pass around your dataset across a wire.  An IDataReader is connected and streams your data to some source in this case our object.  It should also be known that a DataSet internally uses a IDataReader to populate the DataTables.

Some Performance

For our examples we populated our Books table with 50,000 records and used each method to populate 50,000 book objects. (Ran in release mode)

Mapped: 50000 Records in 1115894 Ticks via DataSet
Mapped: 50000 Records in 563554 Ticks via ExecuteSqlStringAccessor
Mapped: 50000 Records in 562318 Ticks via IDataReader/IDataRecord

As you can see the slowest DataSet since to construct the DataSet the code first has to fill the data set completely and then we end up looping over the data again to create our book objects.  This would explain the slowness since we enumerate over the data twice.  The other two IDataRecord and ExecuteSqlStringAccessor are pretty much tied in performance since they only need to enumerate over the result set once.

Conclusion

If you only use a DataSet to map to objects your best avenue is to use an IDataReader instead.  By doing this you also might see improvements in performance under load and also less memory usage as you can map directly from your IDataRecord to your object instead of using the middleman of DataSet.  If I had to choose which one to use I would always go with ExecuteSqlStringAccessor as it gives almost equal performance of IDataReader minus the manual mapping in using IDataRecord directly.

January 6, 2011 6:20pm
Two ways to retrieve the identity from an insert using Enterprise Library

When building a database driven application eventually you will insert some value into a table.  One of the issues you might run into is that once you inserted this information you need to retrieve the identity of the newly created row.  Your first approach might be to insert the data and then query the database again to find your record.

const string bookFormat = "Book Added '{0}' Id:{1} ISBN:{2}";

var bookWithAnotherSelect = new Book
                                {
                                    Name = "Book With Another Select",
                                    ISBN = Guid.NewGuid()
                                };

AddBookWithNonQuery(bookWithAnotherSelect);
Book theBook = GetBook(bookWithAnotherSelect.Name, bookWithAnotherSelect.ISBN);
Console.WriteLine(bookFormat, theBook.Name, theBook.Id, theBook.ISBN);
private static void AddBookWithNonQuery(Book book)
{
    var database = DatabaseFactory.CreateDatabase("SampleDb");
    var command = database.GetStoredProcCommand("[dbo].[AddBook]");
    database.AddInParameter(command, "@Name", DbType.String, book.Name);
    database.AddInParameter(command, "@ISBN", DbType.Guid, book.ISBN);
    database.ExecuteNonQuery(command);
}
private static Book GetBook(string name, Guid isbn)
{
    var database = DatabaseFactory.CreateDatabase("SampleDb");
    var command =
        database.GetSqlStringCommand(
            "SELECT [BookId], [Name], [ISBN] FROM Books WHERE [Name] = @Name AND [Isbn] = @ISBN");
    database.AddInParameter(command, "@Name", DbType.String, name);
    database.AddInParameter(command, "@ISBN", DbType.Guid, isbn);
    Book book = null;
    using (var reader = database.ExecuteReader(command))
    {
        if (reader.Read())
        {
            book = new Book
                       {
                           Id = Convert.ToInt32(reader["BookId"]),
                           Name = reader["Name"].ToString(),
                           ISBN = Guid.Parse(reader["ISBN"].ToString())
                       };
        }
    }

    return book;
}

 

This approach works as long as you can safely query the database with a compound query to produce your result in this case book name and isbn.  However as you notice this method is not as efficient as it relies on an additional query to pull back the Id that is generated by the database.

A Better Approach

There are three ways you could achieve the method of returning the identity, ExecuteScalar, out parameters, or a return value.  I will go over two more popular options of execute scalar and out parameters.

Execute Scalar

var selectBook = new Book
                     {
                         Name = "Adding Via Select",
                         ISBN = Guid.NewGuid()
                     };

AddBookWithSelectReturningId(selectBook);
Console.WriteLine(bookFormat, selectBook.Name, selectBook.Id, selectBook.ISBN);
private static void AddBookWithSelectReturningId(Book book)
{
    var database = DatabaseFactory.CreateDatabase("SampleDb");
    var command = database.GetStoredProcCommand("[dbo].[AddBookWithSelectReturningId]");
    database.AddInParameter(command, "@Name", DbType.String, book.Name);
    database.AddInParameter(command, "@ISBN", DbType.Guid, book.ISBN);
    var bookId = Convert.ToInt32(database.ExecuteScalar(command));
    book.Id = bookId;
}
ALTER PROCEDURE [dbo].[AddBookWithSelectReturningId]
     @Name as varchar(50)
    ,@ISBN as uniqueidentifier
AS
BEGIN
    INSERT INTO Books(Name, ISBN)
        VALUES(@Name, @ISBN)
    
    SELECT SCOPE_IDENTITY()
END

As you can see above this approach is similar however instead of calling into Execute Non Query we are calling Execute Scalar.  Execute Scalar simply returns the first row and first column of a result set.  Since our stored procedure only has one select execute scalar works perfectly.  One note to see here is that ExecuteScalar returns an object so you need to call convert to int32 to get a valid integer value back.

Out Parameters

var outBook = new Book
                  {
                      Name = "Adding Via Out Parameter",
                      ISBN = Guid.NewGuid()
                  };
AddBookWithOutParameter(outBook);
Console.WriteLine(bookFormat, outBook.Name, outBook.Id, outBook.ISBN);
private static void AddBookWithOutParameter(Book book)
{
    var database = DatabaseFactory.CreateDatabase("SampleDb");
    var command = database.GetStoredProcCommand("[dbo].[AddBookWithOutParameter]");
    database.AddInParameter(command, "@Name", DbType.String, book.Name);
    database.AddInParameter(command, "@ISBN", DbType.Guid, book.ISBN);
    database.AddOutParameter(command, "@BookId", DbType.Int32, 4);
    database.ExecuteNonQuery(command);
    var bookId = Convert.ToInt32(database.GetParameterValue(command, "@BookId"));
    book.Id = bookId;
}
ALTER PROCEDURE AddBookWithOutParameter
    @Name as varchar(50)
    ,@ISBN as uniqueidentifier
    ,@BookId as int out
AS
BEGIN
    INSERT INTO Books(Name, ISBN)
        VALUES(@Name, @ISBN)
    
    SET @BookId = SCOPE_IDENTITY()
END

The magic here happens with the way our stored procuedre is developed.  Our procedure has an additional argument of @BookId that is declared as an out parameter.  Because of this we also need to adjust our parameters in AddBookWithOutParameter.  To add in an out parameter we simply use the method AddOutParameter which needs a command, the name of the variable, the type, and a size in bytes (int32 4 bytes, int64 8bytes).  Once we have that constructed we can simply call ExecuteNonQuery.  After the query is executed we can pull off the out parameter by calling GetParameterValue with the command and out parameter name.  This method also returns an object and you need to call convert to int32 to get our Id. 

Which to use?

From various articles the performance of ExecuteScalar and using out parameters are almost identical.  So it really depends on the need of your code.  If you are only returning one value ExecuteScalar will work perfectly and  is slightly less code.  If you need to return multiple values from an insert without a result set you can declare multiple out parameters and pull each one of in your code.

Performance

I took each three methods (two queries, Select, and out parameter) and ran each in a loop creating 1000 records.

RunNonQuery Ticks: 3421067 
RunSelectId Ticks: 1461149 
RunOutParam Ticks: 1726577

From these results you can see Select and Out parameter are fairly close.  However NonQuery is taking about twice as long which is expected since each insert relies on another query to pull back the result.  If performance is the key I would recommend either using option 2 or option 3. (plus it is easier!)

January 4, 2011 7:10pm
Using ToLookup

One of the few extension methods that I hardly ever seem to use is ToLookup, so today I decided to learn what is ToLookup.

What is ToLookup?

ToLookup(keySelector) is an enumerable extension method that allows you to generate a ILookup<TKey, TElement>.  Ok, so now what is an ILookup<TKey, TElement>?  ILookup is simply defined as a collection of keys and 1 or more elements for that key.  In other words you are grouping your collection based upon your key selector.  If you look at ILookup some more you also see that ILookup also implements IEnumberable of IGrouping<TKey, TElement>.  So the next question is what the is IGrouping<Tkey,TElement>?  An IGrouping<TKey,TElement> is another collection as well but this time it is a collection of elements that share the same key.  Ok that makes sense lets look again at IGrouping and we see it also implements IEnumerable of TElement which now is collection of our elements that share the key from IGrouping.

The Chain

ILookup<TKey, TElement> is a collection of IGrouping<TKey,TElement>, which is a collection of IEnumerable<TElement>

Using ToLookup (The Example)

In our example we are going to use a customer object which contains a product bought and the price it was purchased at.

public class Customer
{
    public int Id { get; set; }
    public string Number { get; set; }
    public string ProductBought { get; set; }
    public decimal PriceWhenBought { get; set; }
}

Now to use ToLookup we need a collection of Customers

IEnumerable<Customer> customers = GetAllCustomers();

Next step is to create the ILookup<TKey, TElement>, this is done simply by calling the ToLookup extention method.  However we can not simply just call ToLookup we also need to supply a selector that we wish to us as our TKey

ILookup<string, Customer> customerLookup = customers.ToLookup(c => c.Number);

By doing this now we see that our TKey is going to be our customer number and the elements are going to be each customer object that has the same number.  Since we know that ILookup<TKey, TElement> is a collection we can simply enumerate over the results.

foreach (IGrouping<string, Customer> customerGrouping in customerLookup)
{
}

By enumerating the results we are left with an IGrouping<string, Customer>  This grouping is one key value with all corresponding Customer objects for that key.

foreach (IGrouping<string, Customer> customerGrouping in customerLookup)
{
    Console.WriteLine("Customer: {0}", customerGrouping.Key);
}

The customerGrouping.Key is actually our customer number which was generated by our key selector func of c=> c.Number.  The next question is how do we get the customers that are in this key?  Since IGrouping<TKey, TElement> is also enumerable we can simply enumerate over this to get our customers.

foreach (IGrouping<string, Customer> customerGrouping in customerLookup)
{
    Console.WriteLine("Customer: {0}", customerGrouping.Key);
    foreach (Customer customer in customerGrouping)
    {
        Console.WriteLine("\t {0} {1}", customer.ProductBought, customer.PriceWhenBought.ToString("c"));
    }
}

By enumerating our grouping we now have our customers and can output the information we need.

Customer: 10
         Cd $0.57
         Cd $2.57
         Cd $4.57
         Cd $6.57
         Cd $8.57
         Cd $10.57
         Cd $12.57
         Cd $14.57
         Cd $16.57
         Cd $18.57
Customer: 11
         Dvd $0.57
         Dvd $3.57
         Dvd $6.57
         Dvd $9.57
         Dvd $12.57
         Dvd $15.57
         Dvd $18.57
Customer: 12
         Table $0.57
         Table $4.57
         Table $8.57
         Table $12.57
         Table $16.57
Customer: 13
         Chair $1.57
         Chair $2.57
         Chair $3.57
         Chair $5.57
         Chair $6.57
         Chair $7.57
         Chair $9.57
         Chair $10.57
         Chair $11.57
         Chair $13.57
         Chair $14.57
         Chair $15.57
         Chair $17.57
         Chair $18.57
         Chair $19.57

Awesome!  using the simple ToLookup method allowed us to quickly and easily group our customers based upon Customer Number.

Advanced Usage:

You can also supply an element selector for our elements, this selector allows you to project an anonymous type as our element instead of our customer.

IEnumerable<Customer> customers = GetAllCustomers();

var lookup = customers.ToLookup(c => c.Number, c => new {Price = c.PriceWhenBought, Name = c.ProductBought});

foreach (var customerGrouping in lookup)
{
    Console.WriteLine("Customer: {0}", customerGrouping.Key);
    foreach (var item in customerGrouping)
    {
        Console.WriteLine("\t {0} {1}", item.Name, item.Price.ToString("c"));
    }
}

as you can see above our element is now  c => new {Price = c.PriceWhenBought, Name = c.ProductBought}  which just pulls off two values from our customer as our collection of elements.

December 31, 2010 7:03pm
Going parallel with .NET 4

One of the great new features of .NET 4 is the parallel task library which easily lets you turn simple for loops and foreach loops into multi-core aware tasks. 

Our Examples:

For the example we are going to simply iterate over a collection of items and perform some hard work inside that collection.  Our hard work could be almost any task but for simplicity we are going to treat the hard work as just iterating over the collection again.

var range = Enumerable.Range(0, 10000).ToList();

Action<int> hardWork = i =>
{
    for (int j = 0; j < range.Count; j++)
    {
    }
};

for(;;)

Lets start off with the simple for loop

private static void ForLoop(IList<int> range, Action<int> work)
{
    var stopwatch = new Stopwatch();

    stopwatch.Start();
    for (int i = 0; i < range.Count; i++)
    {
        work(i);
    }
    stopwatch.Stop();

    Console.WriteLine("Total Elapsed Milliseconds for(;;): {0}", stopwatch.ElapsedMilliseconds);
}

If you run this example you will see the elapsed milliseconds to be around +/- 483.

Now that we have our baseline lets attempt to convert this for loop to use the Parallel.For method.

private static void ParallelFor(List<int> range, Action<int> hardWork)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
    Parallel.For(0, range.Count, hardWork);
    stopwatch.Stop();

    Console.WriteLine("Total Elapsed Milliseconds  Parallel.For(): {0}", stopwatch.ElapsedMilliseconds);
}

This signature for Parallel.For is quite simple, our from value, our to value, and what action we wish to take during each iteration.  If we run this example again we see that the total elapsed time for Parallel.For is 139 milliseconds which is approximately 350 milliseconds faster!  What ends up happening here is that Parallel.For will spin up additional threads to iterate over your collection and perform the action thus speeding up your processing time.

foreach()

Using our same starting point lets convert our for loop over to a foreach loop.

private static void ForEach(IEnumerable<int> range, Action<int> work)
{
    var stopwatch = new Stopwatch();

    stopwatch.Start();
    foreach (var i in range)
    {
        work(i);
    }
    stopwatch.Stop();

    Console.WriteLine("Total Elapsed Milliseconds foreach(): {0}", stopwatch.ElapsedMilliseconds);
}

Running this example gives you around the same millisecond duration as the for loop. 

Now if we want to convert this to a Parallel.ForEach you simply do the following:

private static void ParallelForEach(IEnumerable<int> range, Action<int> hardWork)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
    Parallel.ForEach(range, hardWork);
    stopwatch.Stop();

    Console.WriteLine("Total Elapsed Milliseconds  Parallel.ForEach(): {0}", stopwatch.ElapsedMilliseconds);
}

This signature for the Parallel.ForEach is the collection you want to iteration over and the action you wish to perform in this case it is Action<int>.  Our elapsed time is almost identical for our Parallel.For loop example above.

Some Gotchas

Now seeing this you might ask Parallel.For[Each] is the new hotness and we should use it EVERYWHERE!  However this is not exactly the case. 

Consider the following:

public static void Run()
{
    var range = Enumerable.Range(0, 1000).ToList();

    Action<int> hardWork = i =>
                          {
                              for (int j = 0; j < 10; j++)
                              {
                              }
                          };

    ForLoop(range, hardWork);
    ParallelFor(range, hardWork);
    //ForEach(range, hardWork);
   // ParallelForEach(range, hardWork);
}
private static void ForLoop(IList<int> range, Action<int> work)
{
    var stopwatch = new Stopwatch();

    stopwatch.Start();
    for (int i = 0; i < range.Count; i++)
    {
        work(i);
    }
    stopwatch.Stop();

    Console.WriteLine("Total Elapsed Ticks for(;;): {0}", stopwatch.ElapsedTicks);
}
private static void ParallelFor(List<int> range, Action<int> hardWork)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
    Parallel.For(0, range.Count, hardWork);
    stopwatch.Stop();

    Console.WriteLine("Total Elapsed Ticks  Parallel.For(): {0}", stopwatch.ElapsedTicks);
}

Now all we did here was decrease the number of times we iterate over the collection and make the hard work less “hard”.  We also changed the stopwatch to give us elapsed ticks instead of milliseconds for a more precise measurement.

Total Elapsed Ticks for(;;): 370 
Total Elapsed Ticks  Parallel.For(): 2352

How is this possible?  More threads, multi-core, parallel, it should be faster always!  but this is not always the case as there is additional overhead on building up and starting these threads.  If the work is known to be small writing a simple for loop/foreach loop most of the time will be faster.

Thread Local

Another option for the Parallel library is initializing a variable for each thread iterating over the collection.  This could become handy if you are iterating over a huge collection and want to create an instance to some service for each thread to use instead of using one global instance.

Example.

private class MyService
{
    public MyService()
    {
        Console.WriteLine("My Service Created");
    }

    public void Close()
    {
        Console.WriteLine("My Service Closed");
    }
}

This is a sample class that simply outputs when the service is created and when it is closed.  Now to use this service as a thread local in our Parallel.ForEach()

private static void ParallelForEachThreadLocal(List<int> range, Action<int> hardWork)
{
    var stopwatch = new Stopwatch();

    stopwatch.Start();
    Parallel.ForEach(range, () => new MyService(), (i, loopState, myService) =>
                                                       {
                                                           hardWork(i);
                                                           return myService;
                                                       }, service => service.Close());
    stopwatch.Stop();

    Console.WriteLine("Total Elapsed Milliseconds foreach(): {0}", stopwatch.ElapsedMilliseconds);
}

Our signature for using thread local is a little bit different. 

  1. We have our collection we want to iterate over.
  2. Our thread local, in this case we want a new instance of MyService per thread.
  3. Next we have our action that will be ran over each iteration,  This signature now is a bit different, first we have our int, next the loopState, and our newly introduced thread local variable of myService, this function also has to return our thread local so it can be used for the next iteration.
  4. Our final action then is the finally action we wish to perform on our thread local instance.  In this case we want to simply call Close()

If you run our example you can easily see our output and how the threads insatiate a new instance of MyService and then close it down when the iteration is finished.

My Service Created
My Service Created
My Service Created
My Service Created
My Service Created
My Service Closed
My Service Closed
My Service Closed
My Service Closed
My Service Closed
Total Elapsed Milliseconds : 122

Well that just touches the surface of the Parallel library in .NET 4.0 if you wish to learn more check out msdn at the Task Parallel Library.

Liked posts on Tumblr: More liked posts »