Back to List

Have Your Pi and Eat it Too: A Comparison of C# and C++ Performance

John Ptacek John Ptacek  |  
Mar 14, 2013
 

​In honor of National Pi Day, we thought it would be fun to calculate Pi and talk about performance differences between C# and C++. There is some math coming your way (yeah, MATH!), so feel free to skip to the end for a discussion on performance if math isn’t your thing.

So, back in the day, when things where WAY different, Pi was calculated using a mathematical series. One of the more famous ones uses the arctan math function to calculate the value of π. This is called the Leibniz formula for π and is represented by:

Now, this is one of the more inefficient ways to calculate π, it takes about 10 million terms to get an accuracy of 7 decimal places. For those of us asking for performance differences between languages though, that is great!

We have written two programs to calculate π, one in C# and one in C++. They are both syntactically similar and use the same algorithm. We tried to get as close to an apples to apples comparison as we could, but in comparing two different languages, while we did our best, you are still comparing an apple to an orange.

So, what did we see? We calculated π to 15 decimal points, 3.141592653589793 for those of you keeping track at home. Both programs took almost 100 million iterations to converge … 99,995,330 to be exact. We ran each of the programs 10 times to get an average as shown in the following table:

The calculation of π using C++ is 35% faster that it’s corresponding C# code. This is to be expected. Many modern languages such as C# and Java run through a managed runtime. This brings MANY efficiencies to developers. However, the runtime tends to add overhead when it comes to performance.

The pragmatic folks reading this realize that the benefits of a managed execution environment and modern language generally outweigh performance gains from a language like C++. There are reasons that C# and Java are used instead of C++ because developers can be more productive. Our example here, using a very slow numerical algorithm and running it for ten million iterations is a stretch for most scenarios. The 2.5 second difference for such an intensive calculation, while relatively large in our example, in the grand scheme of things is not that big of a difference.

So why bring it up? It is important to think through performance more and more in today’s computing environment for two reasons. The first is cost. As organizations move to utility-based computing with hosted services, such as Amazon Web Services (AWS) and Microsoft Azure, they are paying for their compute cost. If you can realize performance gains that reduce CPU cycles it has a direct impact on the bottom line. The second reason is that mobile is taking over the world, and mobile users want more battery life, not less. Fewer CPU cycles on a smartphone or tablet will result in better battery life, which makes everyone happy.

It will be very rare that most organizations would use C++ or other “closer to the metal” languages for their Line of Business (LOB) applications. The moral of the story though is for intensive processes in cloud-hosted or mobile environments, you want to be razor focused on optimizing your code for performance, no matter what language you choose.

Both code examples are included below, so for National Pi day, make a circle, calculate some π, eat some pie and enjoy!

C++

// LifeOfPi.cpp : Defines the entry point for the console application.
//
 
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
 
void pi( double *pi_value, int *iterations); 
 
int main ( void ) 
 
      int iterations = 0;     // number of actual loop iterations in pi
      double pi_value = 0;    // computed value of pi
 
      clock_t cBegin = (double)clock () ;
      pi(&pi_value, &iterations); 
      printf("   %0.15f with %d iterations\n",  pi_value, iterations); 
      clock_t cEnd = (double) clock() ;
 
      std::cout << float( cEnd - cBegin )
 
 
return 0; 
 
}   
 
void pi( double *pi_value, int *iterations) 
      int i; 
      int k=1;
      double realPi = 3.141592653589793;
      double epsilon = 0.00000001;
      double delta=10;
      *pi_value= 0;
      while (delta>epsilon) {
            *pi_value += pow(-1,(k+1))/(2*k-1);
            delta = fabs((4* *pi_value)-realPi);
            k++;
      }
      *iterations = k;
      *pi_value = 4 * *pi_value;
 
 
      return; // indicate program ended sucessfully
 
} // end fucntion main
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace LifeOfPiCSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            int iterations = 0;
            double pi_value = 0;
 
            DateTime startTime = DateTime.Now;
            pi(out pi_value,out iterations);
            DateTime endTime = DateTime.Now;
            Console.WriteLine(pi_value.ToString() + " in " + iterations);
            TimeSpan diff = endTime.Subtract(startTime);
            Console.WriteLine(diff.Seconds + "."+diff.Milliseconds);
        }
 
        public static void pi(out double pi_value, out int totalIterations)
        {
            double realPi = 3.141592653589793;
            double epsilon = 0.00000001;
            double delta = 10;
            int k = 1;
           
            pi_value = 0;
            while (delta > epsilon)
            {
                pi_value += Math.Pow(-1, (k + 1)) / (2 * k - 1);
                delta = Math.Abs((4 * pi_value) - realPi);
                k++;
            }
            totalIterations = k;
            pi_value = 4 * pi_value;
 
        }
    }
}



 

Love our Blogs?

Sign up to get notified of new Skyline posts.

 


Related Content


Blog Article
Async, Await, and ConfigureAwait – Oh My!
Dan LorenzDan Lorenz  |  
Dec 11, 2018
In .NET Framework 4.5, async/await keywords were added to the language to make async programming easier to work with. In order to maximize device resources and not block UI, you should really try to use asynchronous programming wherever you can. While async/await has made this much easier than...
Blog Article
How to Add Electronic and Digital Signatures to a Universal Application (UWP) with iText
Paul MadaryPaul Madary  |  
Aug 14, 2018
When paying for gas at the pump, checking out at Walmart, or electronically signing a contract to purchase real estate, have you ever thought about what technically goes into that electronic signature?  If not, then this is your lucky day! I recently had to implement this functionality in a...
Blog Article
Updated Mile of Music App Provides an Even Better User Experience
John PtacekJohn Ptacek  |  
Jul 26, 2018
As we get to the end of July at Skyline Technologies, our organization starts to get excited. We know that the Mile of Music festival is just around the corner. With over 70,000 people coming to Appleton, Wisconsin, for four days of original music, it is quite an adventure. Given one of the main...
Blog Article
WinForms Fluid Design - A Cautionary Tale
Jeff LucasJeff Lucas  |  
May 01, 2018
As a developer, you can find yourself digging into all sorts of code, even the occasional WinForms application.  WinForms come with a lot of handy features that can make fluid design quite simple, allowing your forms to be resized by the user but still hold the basic shape you desire without...
Blog Article
Using SignalR Base Classes in Angular
Eric DitterEric Ditter  |  
Mar 06, 2018
On one of my previous projects I used SignalR extensively in an Angular 1.6 application, and I was using the angular-signalr-hub library to integrate it into the application. It worked very well, but I am moving to the next version of Angular so I wanted to find a way to do it without having to...