C # против C - большая разница в производительности - PullRequest
92 голосов
/ 26 марта 2009

Я нахожу огромные различия в производительности между похожим кодом в C anc C #.

Код C:

#include <stdio.h>
#include <time.h>
#include <math.h>

main()
{
    int i;
    double root;

    clock_t start = clock();
    for (i = 0 ; i <= 100000000; i++){
        root = sqrt(i);
    }
    printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC);   

}

А C # (консольное приложение):

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            DateTime startTime = DateTime.Now;
            double root;
            for (int i = 0; i <= 100000000; i++)
            {
                root = Math.Sqrt(i);
            }
            TimeSpan runTime = DateTime.Now - startTime;
            Console.WriteLine("Time elapsed: " + Convert.ToString(runTime.TotalMilliseconds/1000));
        }
    }
}

При использовании приведенного выше кода C # завершается за 0,328125 секунд (версия выпуска), а запуск C занимает 11,14 секунды.

C компилируется в исполняемый файл Windows, используя mingw.

Я всегда исходил из того, что C / C ++ были быстрее или, по крайней мере, сопоставимы с C # .net. Что именно заставляет C работать в 30 раз медленнее?

EDIT: Похоже, что оптимизатор C # удалял рут, поскольку он не использовался. Я изменил корневое назначение на root + = и распечатал итог в конце. Я также скомпилировал C, используя cl.exe с флагом / O2, установленным для максимальной скорости.

Результаты теперь: 3,75 секунды для C 2,61 секунды для C #

C все еще занимает больше времени, но это приемлемо

Ответы [ 13 ]

2 голосов
/ 26 марта 2009

Другой фактор, который может быть проблемой, заключается в том, что компилятор C компилируется в общий родной код для целевого семейства процессоров, тогда как MSIL, сгенерированный при компиляции кода C #, затем JIT-компилируется для нацеливания именно на ваш процессор в комплекте с любыми возможными оптимизациями. Таким образом, нативный код, сгенерированный из C #, может быть значительно быстрее, чем C.

1 голос
/ 26 марта 2009

На самом деле, ребята, цикл НЕ оптимизируется. Я скомпилировал код Джона и изучил полученный .exe. Внутренности цикла следующие:

 IL_0005:  stloc.0
 IL_0006:  ldc.i4.0
 IL_0007:  stloc.1
 IL_0008:  br.s       IL_0016
 IL_000a:  ldloc.1
 IL_000b:  conv.r8
 IL_000c:  call       float64 [mscorlib]System.Math::Sqrt(float64)
 IL_0011:  pop
 IL_0012:  ldloc.1
 IL_0013:  ldc.i4.1
 IL_0014:  add
 IL_0015:  stloc.1
 IL_0016:  ldloc.1
 IL_0017:  ldc.i4     0x5f5e100
 IL_001c:  ble.s      IL_000a

Если среда выполнения не достаточно умна, чтобы понять, что цикл ничего не делает и пропускает его?

Edit: Изменение C # на:

 static void Main(string[] args)
 {
      DateTime startTime = DateTime.Now;
      double root = 0.0;
      for (int i = 0; i <= 100000000; i++)
      {
           root += Math.Sqrt(i);
      }
      System.Console.WriteLine(root);
      TimeSpan runTime = DateTime.Now - startTime;
      Console.WriteLine("Time elapsed: " +
          Convert.ToString(runTime.TotalMilliseconds / 1000));
 }

Результаты за прошедшее время (на моей машине) с 0,047 до 2,17. Но это только накладные расходы на добавление 100 миллионов операторов сложения?

1 голос
/ 26 марта 2009

Мне кажется, что это не имеет ничего общего с самими языками, скорее это связано с различными реализациями функции квадратного корня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...