views:

410

answers:

4

In Code Complete 2 (page 601 and 602) there is a table of "Cost of Common Operations".

The baseline operation integer assignment is given a value 1 and then the relative time for common operations is listed for Java and C++. For example:

                                  C++        Java
Integer assignment                1             1
Integer division                  5             1.5
Floating point square root       15             4

The question is has anyone got this data for C#? I know that these won't help me solve any problems specifically, I'm just curious.

+7  A: 

I implemented some of the tests from the book. Some raw data from my computer:

Test Run #1:

TestIntegerAssignment 00:00:00.6680000
TestCallRoutineWithNoParameters 00:00:00.9780000
TestCallRoutineWithOneParameter 00:00:00.6580000
TestCallRoutineWithTwoParameters 00:00:00.9650000
TestIntegerAddition 00:00:00.6410000
TestIntegerSubtraction 00:00:00.9630000
TestIntegerMultiplication 00:00:00.6490000
TestIntegerDivision 00:00:00.9720000
TestFloatingPointDivision 00:00:00.6500000
TestFloatingPointSquareRoot 00:00:00.9790000
TestFloatingPointSine 00:00:00.6410000
TestFloatingPointLogarithm 00:00:41.1410000
TestFloatingPointExp 00:00:34.6310000

Test Run #2:

TestIntegerAssignment 00:00:00.6750000
TestCallRoutineWithNoParameters 00:00:00.9720000
TestCallRoutineWithOneParameter 00:00:00.6490000
TestCallRoutineWithTwoParameters 00:00:00.9750000
TestIntegerAddition 00:00:00.6730000
TestIntegerSubtraction 00:00:01.0300000
TestIntegerMultiplication 00:00:00.7000000
TestIntegerDivision 00:00:01.1120000
TestFloatingPointDivision 00:00:00.6630000
TestFloatingPointSquareRoot 00:00:00.9860000
TestFloatingPointSine 00:00:00.6530000
TestFloatingPointLogarithm 00:00:39.1150000
TestFloatingPointExp 00:00:33.8730000

Test Run #3:

TestIntegerAssignment 00:00:00.6590000
TestCallRoutineWithNoParameters 00:00:00.9700000
TestCallRoutineWithOneParameter 00:00:00.6680000
TestCallRoutineWithTwoParameters 00:00:00.9900000
TestIntegerAddition 00:00:00.6720000
TestIntegerSubtraction 00:00:00.9770000
TestIntegerMultiplication 00:00:00.6580000
TestIntegerDivision 00:00:00.9930000
TestFloatingPointDivision 00:00:00.6740000
TestFloatingPointSquareRoot 00:00:01.0120000
TestFloatingPointSine 00:00:00.6700000
TestFloatingPointLogarithm 00:00:39.1020000
TestFloatingPointExp 00:00:35.3560000

(1 Billion Tests Per Benchmark, Compiled with Optimize, AMD Athlon X2 3.0ghz, using Jon Skeet's microbenchmarking framework available at http://www.yoda.arachsys.com/csharp/benchmark.html)

Source:

class TestBenchmark  
{  
[Benchmark]  
public static void TestIntegerAssignment()
{
int i = 1;
int j = 2;

    for (int x = 0; x < 1000000000; x++)
    {
        i = j;
    }
}

[Benchmark]
public static void TestCallRoutineWithNoParameters()
{
    for (int x = 0; x < 1000000000; x++)
    {
        TestStaticRoutine();
    }
}

[Benchmark]
public static void TestCallRoutineWithOneParameter()
{
    for (int x = 0; x < 1000000000; x++)
    {
        TestStaticRoutine2(5);
    }
}

[Benchmark]
public static void TestCallRoutineWithTwoParameters()
{
    for (int x = 0; x < 1000000000; x++)
    {
        TestStaticRoutine3(5,7);
    }
}

[Benchmark]
public static void TestIntegerAddition()
{
    int i = 1;
    int j = 2;
    int k = 3;

    for (int x = 0; x < 1000000000; x++)
    {
        i = j + k;
    }
}

[Benchmark]
public static void TestIntegerSubtraction()
{
    int i = 1;
    int j = 6;
    int k = 3;

    for (int x = 0; x < 1000000000; x++)
    {
        i = j - k;
    }
}

[Benchmark]
public static void TestIntegerMultiplication()
{
    int i = 1;
    int j = 2;
    int k = 3;

    for (int x = 0; x < 1000000000; x++)
    {
        i = j * k;
    }
}


[Benchmark]
public static void TestIntegerDivision()
{
    int i = 1;
    int j = 6;
    int k = 3;

    for (int x = 0; x < 1000000000; x++)
    {
        i = j/k;
    }
}

[Benchmark]
public static void TestFloatingPointDivision()
{
    float i = 1;
    float j = 6;
    float k = 3;

    for (int x = 0; x < 1000000000; x++)
    {
        i = j / k;
    }
}

[Benchmark]
public static void TestFloatingPointSquareRoot()
{
    double x = 1;
    float y = 6;

    for (int x2 = 0; x2 < 1000000000; x2++)
    {
        x = Math.Sqrt(6);
    }
}

[Benchmark]
public static void TestFloatingPointSine()
{
    double x = 1;
    float y = 6;

    for (int x2 = 0; x2 < 1000000000; x2++)
    {
        x = Math.Sin(y);
    }
}

[Benchmark]
public static void TestFloatingPointLogarithm()
{
    double x = 1;
    float y = 6;

    for (int x2 = 0; x2 < 1000000000; x2++)
    {
        x = Math.Log(y);
    }
}

[Benchmark]
public static void TestFloatingPointExp()
{
    double x = 1;
    float y = 6;

    for (int x2 = 0; x2 < 1000000000; x2++)
    {
        x = Math.Exp(6);
    }
}

private static void TestStaticRoutine() {

}

private static void TestStaticRoutine2(int i)
{

}

private static void TestStaticRoutine3(int i, int j)
{

}

private static class TestStaticClass
{

}
Robert Venables
that's dedication right there ;)
Eoin Campbell
I'd do something with the result (like Console.WriteLine it) just to make absolutely sure that it doesn't get optimised away. It probably won't, but ...
Mark Simpson
a man with way too much time on his hands (thankfully)
DrG
Don't you think that it's a bit strange every result is either ~0.33, ~0.66 or ~0.99? Especially when calls with 0,1,2 arguments get 0.9, 0.6, 0.9, I'd start getting suspicious about the testing method. Also private static functions can be inlined. That was a very bad test IMHO.
viraptor
A: 

What problem do you want to solve with your benchmarking?

I've worked on projects with problems in performance, and used several tools, like JetBrains Profiler and some memory profiling tools to find out what caused the problem.

Peter R
it's nothing specific, I've been doing project euler and am always looking for ways to tune my solutions...
DrG
+1  A: 

It's a reasonable question, but nearly every performance problem I've seen, especially in Java and C# boiled down to:

  • too many layers of abstraction, and
  • reliance on event-based notification-style coding.

which have little or nothing to do with basic operations.

The problem with abstraction is it is fine until the workload gets heavy. Each layer usually exacts a small performance penalty, and these accumulate in a compounded fashion. At that point you start needing workarounds. (I think StringBuilder is an example of such a workaround.)

The problem with event-based notification-style coding (as opposed to simpler data structures kept consistent by a periodic process) is that what can seem like simple actions, such as setting a property to a value, can result in a ripple effect of actions throughout the data structure doing far more than one might expect.

Mike Dunlavey
+1  A: 

Straight from the source, Know what things cost.

IIRC Rico Mariani had relative measures as the ones you asked for on his blog, I can't find it anymore, though (I know it's in one of thoe twohudnred "dev" bookmarks...)

peterchen