Since most of the issues revolved around solve, let me be more clear in my argument:

- A complex function, even if it is mostly one containing linear flow can be broken down into several simple functions in order to become more hierarchical and less linear. Let me give a simple example to elucidate my point:

Instead of a long function such as:

void Car::Build()

{ // Build the frame

... build the frame code

// Add doors

... add doors code

// Insert engine

... insert engine code

// Insert transmission

... insert transmission code

// Insert upholstery

... insert upholstery code

// Paint the car

... paint the car code

// Whatever else needs to be done

... whatever else needs to be done

}

It is much easier to see (the comments are not part of the code, I am just adding them to show what the functions being called do for the purpose of explaining my point):

Now the Build function is easy to eye over and comprehend. If the programmer wishes to look into detail and see how each step is actually implemented, he can go into each of the functions being called and examine them (or look at call graphs, etc...).

By creating a deeper (rather than shallower) Build() function, it is much easier to comprehend in a top down (rather than bottom up) fashion. This is how most people solve and analyze problems - from an abstract problem statement to analyzing (i.e., "sweating")
the details.

If you:

Break up your solve function into sub-tasks (functions)

Give them meaningful names

Only call these sub-tasks from within solve

Then, it would be much easier to see what solve does as a whole and there would be no performance penalty in doing this, to boot, because these sub-tasks would probably still be gross tasks. If any of the sub-tasks are still complex, you can further decompose
them into more sub-tasks.

A developer reading solve would drill down to the level of interest to him, while seeing the big picture all along the way. Compare this to having to gloss over 400 lines of code, even if only looking for comments, in order to try to figure out what solve
does.

Well, he does state that the solve function, the meat of this application, will be covered in the next video, so I suppose we can take a wait and see approach. However, basic OO/structured programming tenets do not condone the use of 400 line "super-do-everything"
functions, of which solve() is one. Bottom line is that we'll have to give Stephan the benefit of the doubt and let him elaborate in the next episode...

So, I opened the source file, saw a nearly 400 line solve function with minimal "island" comments and pretty much lost all interest in what the program does. Just my two cents worth... Does it really have to be this unstructured to perform? Can it be any
less structured and still be instructive (/sarcasm)? Was it necessary to cram it all into one .cpp file, given that it was part of a zip archive?

Why didn't you guys use a tripod? The tiny screen in the video is very hard to read and the camera shake makes it even harder. Fortunatelly, the code was posted to the right of the video (and the subtitles helped, too), because it was nearly impossible to
make it out on the screen. In the end, I think this entire exercise would have been better as a post to a blog.

Before uploading, please do a good job of compressing the video. It is VC-1 compression after all and the WMV-High version should not suffer posterization, blocking and other highly noticeable artifacts, making it not much better than the regular WMV version.

I am sorry, most of the videos from this MSDN simulcast have shoddy audio, but the audio on this presentation is barely legible. Is this 2010 or 1910? Horrible echo combined with audio compression beyond any reasonable limit leads to audio that one has to
strain oneself to an extreme in order to be able to understand. There is also a complete audio drop from 5:06 to 5:29 during the presentation.

For anyone interested in the scalability of the various approaches presented, here are the results of a proper 64-bit release mode run on a more modern box with 6GB of RAM and a single Intel Xeon W5590 CPU (3.33 GHz / 8MB L3 cache quad-core Nehalem-EP with
hyperthreading turned on for a total of 8 logical CPUs). The build was done using VS2010 RC / .NET 4.0 RC and run on the host I just gave the specs for, under the Windows 2008 R2 Standard OS:

CalcPrimes
Count of prime numbers: 283146
Elapsed = 1713

ThreadingDemo.CalcPrimes
Count of prime numbers: 283146
Elapsed = 1080

ParallelFor.CalcPrimes
Count of prime numbers: 283146
Elapsed = 431

ParallelForEach.CalcPrimes
Count of prime numbers: 283146
Elapsed = 481

ParallelFor.CalcPrimes_TLV
Count of prime numbers: 283146
Elapsed = 430

ParallelForEach.CalcPrimes_TLV
Count of prime numbers: 283146
Elapsed = 447

LinqDemo.CalcPrimes
Count of prime numbers: 283146
Elapsed = 1740

PLinqDemo.CalcPrimes
Count of prime numbers: 283146
Elapsed = 461

Summary: It looks like, with a proper release 64-bit build, there are many options available here to gain the scalability, at least with this particular test and the specified number of CPUs.

Interestingly, if we make a slight improvement to the algorithm we can improve performance and most likely not even need to consider multithreaded approaches. Also, we can leverage the contents of the container we are forming without worrying about (and
paying a concurrency penalty for) locking it, as follows:

for (int nr = 3; nr <= 4000000; nr+=2) { int upperBound=(int) Math.Sqrt(nr);

foreach (int prime in primes) { if (prime > upperBound) { primes.Add(nr); break; }

if (nr % prime == 0) break; } } Console.WriteLine("Count of prime numbers: " + primes.Count); }

Running with these small changes, we get:

CalcPrimes2 (Single-Threaded)
Count of prime numbers: 283146
Elapsed = 501

Notices how this result is comparable to our best multi-threaded results.

For the next test, let's increase the number of numbers being tested for primality to 8 million and see how the various approaches fair:

CalcPrimes
Count of prime numbers: 539777
Elapsed = 4585

CalcPrimes2 (Single-Threaded)
Count of prime numbers: 539777
Elapsed = 1224

ThreadingDemo.CalcPrimes
Count of prime numbers: 539777
Elapsed = 2870

ParallelFor.CalcPrimes
Count of prime numbers: 539777
Elapsed = 1146

ParallelForEach.CalcPrimes
Count of prime numbers: 539777
Elapsed = 1210

ParallelFor.CalcPrimes_TLV
Count of prime numbers: 539777
Elapsed = 1144

ParallelForEach.CalcPrimes_TLV
Count of prime numbers: 539777
Elapsed = 1178

LinqDemo.CalcPrimes
Count of prime numbers: 539777
Elapsed = 4623

PLinqDemo.CalcPrimes
Count of prime numbers: 539777
Elapsed = 1183

Now, the slightly improved single threaded function (CalcPrimes2) is almost in line with out best parallel attempt, using the previous algorithm, despite the fact that this is a decent multi-processor host (i.e., 4 physical, 8 logical CPU cores) which allows
for a lot of potential parallelism to the various decent parallel approaches presented in this session. This example (i.e., extending the domain of numbers being tested to 8 million) and how it scales as the workload increases, underlines the point about taking
a little time to improve the algorithm first, before jumping with both feet into a multi-threaded solution.

If you are still not convinced, let's look at what happens when the domain is doubled again to the first 16 million numbers:

CalcPrimes
Count of prime numbers: 1031130
Elapsed = 12248

CalcPrimes2 (Single-Threaded)
Count of prime numbers: 1031130
Elapsed = 3017

ThreadingDemo.CalcPrimes
Count of prime numbers: 1031130
Elapsed = 7682

ParallelFor.CalcPrimes
Count of prime numbers: 1031130
Elapsed = 3054

ParallelForEach.CalcPrimes
Count of prime numbers: 1031130
Elapsed = 3119

ParallelFor.CalcPrimes_TLV
Count of prime numbers: 1031130
Elapsed = 3052

ParallelForEach.CalcPrimes_TLV
Count of prime numbers: 1031130
Elapsed = 3103

LinqDemo.CalcPrimes
Count of prime numbers: 1031130
Elapsed = 12318

PLinqDemo.CalcPrimes
Count of prime numbers: 1031130
Elapsed = 3106

In this run, the (improved) single-threaded solution (marginally) beats our best parallel attempts with the weaker algorithm.

## Comments

## Building Awesome Apps for Windows 7 (Session 1): A Lap Around the Windows API Code Pack

How does this relate to WPF for doing the exact same thing?

## Building Awesome Apps for Windows 7: Overview

Wait, what's wrong with WPF for building these same managed apps without downloading any of this Windows API code pack mumbo jumbo?

## C9 Lectures: Stephan T. Lavavej - Standard Template Library (STL), 4 of n

Looking much better in 1.3! I'd still do more refactoring on unreachable(), but it's a whole world better than before...

## C9 Lectures: Stephan T. Lavavej - Standard Template Library (STL), 4 of n

Since most of the issues revolved around solve, let me be more clear in my argument:

- A complex function, even if it is mostly one containing linear flow can be broken down into several simple functions in order to become more hierarchical and less linear. Let me give a simple example to elucidate my point:

Instead of a long function such as:

void Car::Build(){// Build the frame

... build the frame code// Add doors... add doors code// Insert engine... insert engine code// Insert transmission... insert transmission code// Insert upholstery... insert upholstery code// Paint the car... paint the car code// Whatever else needs to be done... whatever else needs to be done}It is much easier to see (the comments are not part of the code, I am just adding them to show what the functions being called do for the purpose of explaining my point):

void Car::Build(){BuildFrame(...); // Calls AddDoors()

AddInternalParts(...); // Calls AddEngine(), AddTransmission(), AddUphostery()?, etc...AddBodyParts(...); // Calls AddDoors()Paint(...);}Now the Build function is easy to eye over and comprehend. If the programmer wishes to look into detail and see how each step is actually implemented, he can go into each of the functions being called and examine them (or look at call graphs, etc...).

By creating a deeper (rather than shallower) Build() function, it is much easier to comprehend in a top down (rather than bottom up) fashion. This is how most people solve and analyze problems - from an abstract problem statement to analyzing (i.e., "sweating") the details.

If you:

Then, it would be much easier to see what solve does as a whole and there would be no performance penalty in doing this, to boot, because these sub-tasks would probably still be gross tasks. If any of the sub-tasks are still complex, you can further decompose them into more sub-tasks.

A developer reading solve would drill down to the level of interest to him, while seeing the big picture all along the way. Compare this to having to gloss over 400 lines of code, even if only looking for comments, in order to try to figure out what solve does.

My two cents...

## C9 Lectures: Stephan T. Lavavej - Standard Template Library (STL), 4 of n

Well, he does state that the solve function, the meat of this application, will be covered in the next video, so I suppose we can take a wait and see approach. However, basic OO/structured programming tenets do not condone the use of 400 line "super-do-everything" functions, of which solve() is one. Bottom line is that we'll have to give Stephan the benefit of the doubt and let him elaborate in the next episode...

## C9 Lectures: Stephan T. Lavavej - Standard Template Library (STL), 4 of n

So, I opened the source file, saw a nearly 400 line solve function with minimal "island" comments and pretty much lost all interest in what the program does. Just my two cents worth... Does it really have to be this unstructured to perform? Can it be any less structured and still be instructive (/sarcasm)? Was it necessary to cram it all into one .cpp file, given that it was part of a zip archive?

Just my 2 cents...

## Techniques in Advanced .NET Debugging with John Robbins (Part 1 of 3)

I nominate this for the

encoding of a very important presentation to ever grace Channel 9.worst## C# 4.0 and beyond by Anders Hejlsberg

Thanks for posting this wonderful presentation.

Please follow up with more from DevDays 2010. Also, the video and audio quality are superb! All encodings of presentations should be this good.

## How to Embed PowerShell Within a C# Application

Why didn't you guys use a tripod? The tiny screen in the video is very hard to read and the camera shake makes it even harder. Fortunatelly, the code was posted to the right of the video (and the subtitles helped, too), because it was nearly impossible to make it out on the screen. In the end, I think this entire exercise would have been better as a post to a blog.

## TechDays 2010 Keynote by Anders Hejlsberg: Trends and future directions in programming languages

Before uploading, please do a good job of compressing the video. It is VC-1 compression after all and the WMV-High version should not suffer posterization, blocking and other highly noticeable artifacts, making it not much better than the regular WMV version.

Thanks

## All Data/All Day Dive into .NET Data Access (Part 4 of 6): Getting Started with ADO.NET Entity Framework

I am sorry, most of the videos from this MSDN simulcast have shoddy audio, but the audio on this presentation is barely legible. Is this 2010 or 1910? Horrible echo combined with audio compression beyond any reasonable limit leads to audio that one has to strain oneself to an extreme in order to be able to understand. There is also a complete audio drop from 5:06 to 5:29 during the presentation.

## MSDN Live Meeting - Visual Studio 2010 and .NET 4 Update

For anyone interested in the scalability of the various approaches presented, here are the results of a proper 64-bit release mode run on a more modern box with 6GB of RAM and a single Intel Xeon W5590 CPU (3.33 GHz / 8MB L3 cache quad-core Nehalem-EP with hyperthreading turned on for a total of 8 logical CPUs). The build was done using VS2010 RC / .NET 4.0 RC and run on the host I just gave the specs for, under the Windows 2008 R2 Standard OS:

CalcPrimes

Count of prime numbers: 283146

Elapsed = 1713

ThreadingDemo.CalcPrimes

Count of prime numbers: 283146

Elapsed = 1080

ParallelFor.CalcPrimes

Count of prime numbers: 283146

Elapsed = 431

ParallelForEach.CalcPrimes

Count of prime numbers: 283146

Elapsed = 481

ParallelFor.CalcPrimes_TLV

Count of prime numbers: 283146

Elapsed = 430

ParallelForEach.CalcPrimes_TLV

Count of prime numbers: 283146

Elapsed = 447

LinqDemo.CalcPrimes

Count of prime numbers: 283146

Elapsed = 1740

PLinqDemo.CalcPrimes

Count of prime numbers: 283146

Elapsed = 461

Summary: It looks like, with a proper release 64-bit build, there are many options available here to gain the scalability, at least with this particular test and the specified number of CPUs.

Interestingly, if we make a slight improvement to the algorithm we can improve performance and most likely not even need to consider multithreaded approaches. Also, we can leverage the contents of the container we are forming without worrying about (and paying a concurrency penalty for) locking it, as follows:

Running with these small changes, we get:

CalcPrimes2 (Single-Threaded)

Count of prime numbers: 283146

Elapsed = 501

Notices how this result is comparable to our best multi-threaded results.

For the next test, let's increase the number of numbers being tested for primality to 8 million and see how the various approaches fair:

CalcPrimes

Count of prime numbers: 539777

Elapsed = 4585

CalcPrimes2 (Single-Threaded)

Count of prime numbers: 539777

Elapsed = 1224

ThreadingDemo.CalcPrimes

Count of prime numbers: 539777

Elapsed = 2870

ParallelFor.CalcPrimes

Count of prime numbers: 539777

Elapsed = 1146

ParallelForEach.CalcPrimes

Count of prime numbers: 539777

Elapsed = 1210

ParallelFor.CalcPrimes_TLV

Count of prime numbers: 539777

Elapsed = 1144

ParallelForEach.CalcPrimes_TLV

Count of prime numbers: 539777

Elapsed = 1178

LinqDemo.CalcPrimes

Count of prime numbers: 539777

Elapsed = 4623

PLinqDemo.CalcPrimes

Count of prime numbers: 539777

Elapsed = 1183

Now, the slightly improved single threaded function (CalcPrimes2) is almost in line with out best parallel attempt, using the previous algorithm, despite the fact that this is a decent multi-processor host (i.e., 4 physical, 8 logical CPU cores) which allows for a lot of potential parallelism to the various decent parallel approaches presented in this session. This example (i.e., extending the domain of numbers being tested to 8 million) and how it scales as the workload increases, underlines the point about taking a little time to improve the algorithm first, before jumping with both feet into a multi-threaded solution.

If you are still not convinced, let's look at what happens when the domain is doubled again to the first 16 million numbers:

CalcPrimes

Count of prime numbers: 1031130

Elapsed = 12248

CalcPrimes2 (Single-Threaded)

Count of prime numbers: 1031130

Elapsed = 3017

ThreadingDemo.CalcPrimes

Count of prime numbers: 1031130

Elapsed = 7682

ParallelFor.CalcPrimes

Count of prime numbers: 1031130

Elapsed = 3054

ParallelForEach.CalcPrimes

Count of prime numbers: 1031130

Elapsed = 3119

ParallelFor.CalcPrimes_TLV

Count of prime numbers: 1031130

Elapsed = 3052

ParallelForEach.CalcPrimes_TLV

Count of prime numbers: 1031130

Elapsed = 3103

LinqDemo.CalcPrimes

Count of prime numbers: 1031130

Elapsed = 12318

PLinqDemo.CalcPrimes

Count of prime numbers: 1031130

Elapsed = 3106

In this run, the (improved) single-threaded solution (marginally) beats our best parallel attempts with the weaker algorithm.

Thanks for listening