2009-05-16 16 views
7

W Code Complete 2 (strona 601 i 602) znajduje się tabela "Koszt wspólnych operacji".Koszt typowych operacji dla C#?

Podstawowa operacja przypisania liczby całkowitej ma wartość 1, a następnie względny czas dla typowych operacji jest wymieniony dla języków Java i C++. Na przykład:

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

Pytanie, czy ktoś ma te dane dla C#? Wiem, że to nie pomoże mi rozwiązać problemów, jestem po prostu ciekawy.

+0

(i to byłby taki sam dla wszystkich języków .NET) –

+0

lol @ uproszczone testy porównawcze. – gbjbaanb

+0

Wygląda jak przedwczesna optymalizacja przedwczesnej optymalizacji ... Te operacje będą wykonywane w kodzie zespołu, ale test porównawczy będzie działał w rzeczywistym środowisku wykonawczym, a IMHO przetestuje, że benchmark jest wolny, a nie instrukcje maszyny. –

Odpowiedz

4

Prosto ze źródła, Know what things cost.

IIRC Rico Mariani miał środki względne jak te prosiłeś on his blog, nie mogę go znaleźć już, choć (wiem, że to w jednym z thoe twohudnred „dev” zakładki ...)

10

Zaimplementowałam niektóre testy z książki. Niektóre surowe dane z mojego komputera:

Przebieg testowy nr 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

Przebieg testowy nr 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

Przebieg testowy nr 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 mld testów na benchmarku skompilowany z optymalizacji AMD Athlon X2 3.0GHz, wykorzystując ramy microbenchmarking Jon Skeet dostępny na http://www.yoda.arachsys.com/csharp/benchmark.html)

Źródło:

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 
{ 

} 
+4

to dedykacja właśnie tam;) –

+0

Zrobiłbym coś z wynikiem (jak Console.WriteLine to), aby upewnić się, że nie zostanie zoptymalizowany. Prawdopodobnie tak nie będzie, ale ... –

+0

człowiek ze zbyt dużą ilością czasu na rękach (na szczęście) – inspite

1

Jest to uzasadnione pytanie, ale prawie każdy problem wydajność widziałem, szczególnie w Java i C# sprowadzały się do:

  • zbyt wielu warstw abstrakcji i
  • poleganie na kodowaniu stylu powiadomień w oparciu o zdarzenia.

które mają niewiele lub nie mają nic wspólnego z podstawowymi operacjami.

Problem z abstrakcją jest w porządku, dopóki obciążenie nie stanie się ciężkie. Każda warstwa zwykle wymaga niewielkiej kary za wyniki, a te gromadzą się w złożony sposób. W tym momencie zaczynasz potrzebować obejść. (Myślę, że StringBuilder jest przykładem takiego obejścia).

Problem z kodowaniem w stylu powiadomień opartym na zdarzeniach (w przeciwieństwie do prostszych struktur danych utrzymywanych w zgodności z procesem okresowym) jest taki, który może wydawać się prostymi działaniami, takie jak ustawienie właściwości na wartość, może spowodować efekt falujący działań w całej strukturze danych, znacznie przekraczając oczekiwania.

Powiązane problemy