C#的常见操作成本?

时间:2009-05-16 13:30:37

标签: c# performance optimization operators

Code Complete 2(第601和602页)中,有一张“常用操作成本”表。

基线操作整数赋值的值为1,然后列出了Java和C ++的常用操作的相对时间。例如:

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

问题是有没有人得到C#的这些数据?我知道这些不会帮我解决任何问题,我只是好奇。

3 个答案:

答案 0 :(得分:10)

我实施了本书中的一些测试。我计算机上的一些原始数据:

试运行#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

试运行#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

试运行#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

(每个基准测试10亿次,使用Optimize编译,AMD Athlon X2 3.0ghz,使用Jon http://www.yoda.arachsys.com/csharp/benchmark.html提供的Jon Skeet微基准测试框架

来源:

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
{

}

答案 1 :(得分:4)

直接来源 Know what things cost

IIRC Rico Mariani有你所要求的相对措施on his blog,我再也找不到它了(我知道这是在两个“两个”的“dev”书签中......)

答案 2 :(得分:2)

这是一个合理的问题,但几乎我见过的所有性能问题,特别是在Java和C#中归结为:

  • 抽象层次太多,
  • 依赖基于事件的通知式编码。

与基本操作几乎没有任何关系。

抽象问题是在工作量变大之前就可以了。每一层通常都会产生很小的性能损失,并且这些因素会以复合的方式累积。那时你开始需要解决方法。 (我认为StringBuilder就是这种解决方法的一个例子。)

基于事件的通知式编码(与通过周期性过程保持一致的简单数据结构相反)的问题在于,看似简单的操作,例如将属性设置为值,可能会导致波动整个数据结构中的行动效果远远超出人们的预期。