Является.NET 4.0 Временами выполнения медленнее, чем.NET 2.0 Времени выполнения?

После того, как я обновил свои проекты до.NET 4.0 (С VS2010), я понял, чем они работают медленнее, чем они были в.NET 2.0 (VS2008). Таким образом, я решил сравнить простого консольного приложения в обоих VS2008 и VS2010 с различными Целевыми Платформами:

using System;
using System.Diagnostics;
using System.Reflection;

namespace RuntimePerfTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Assembly.GetCallingAssembly().ImageRuntimeVersion);
            Stopwatch sw = new Stopwatch();

            while (true)
            {
                sw.Reset();
                sw.Start();

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

                }

                TimeSpan elapsed = sw.Elapsed;
                Console.WriteLine(elapsed);
            }
        }
    }
}

Вот результаты:

  • VS2008
    • Целевая Платформа 2.0: ~0.25 секунды
    • Целевая Платформа 3.0: ~0.25 секунды
    • Целевая Платформа 3.5: ~0.25 секунды
  • VS2010
    • Целевая Платформа 2.0: ~3.8 секунды
    • Целевая Платформа 3.0: ~3.8 секунды
    • Целевая Платформа 3.5: ~1.51 секунды
    • Целевая Платформа 3.5 Клиентских Профиля: ~3.8 секунды
    • Целевая Платформа 4.0: ~1.01 секунды
    • Целевая Платформа 4.0 Клиентских Профиля: ~1.01 секунды

Мое первоначальное заключение состоит, очевидно в том, что программы скомпилировали с VS2008, работающим быстрее, чем программы, скомпилированные с VS2010.

Кто-либо может объяснить те, которые производительность изменяет между VS2008 и VS2010? и между различными Целевыми Платформами в самом VS2010?

22
задан DxCK 19 May 2010 в 09:21
поделиться

4 ответа

Думаю, я понял.

Если вы работаете на 64-битной машине, убедитесь, что для сборки установлено значение «Любой процессор», а не «x86». Это устранило проблему на моей машине.

Значение по умолчанию для новых проектов в VS2010 изменено с «Любой ЦП» на «x86» - я считаю, что это было сделано для того, чтобы «Редактировать и продолжить» работало по умолчанию на 64-битных машинах (поскольку он поддерживает только x86).

Очевидно, что запуск x86-процесса на 64-битной машине несколько неоптимален.

РЕДАКТИРОВАТЬ: Согласно комментариям Дастина, запуск x86, а не x64 может иметь преимущества в производительности с точки зрения более эффективного использования памяти (более короткие ссылки).

Я также переписывался с Дастином по электронной почте, и он указал следующие причины:

FWIW, целевая платформа по умолчанию. не было изменено для поддержки ENC. Мы имеем уже отправленный ENC сломан на x64 для 2 релиза. Так что сама по себе ENC не была действительно веская причина для перехода. Основные причины, по которым мы перешли (ни в коем случае не в конкретном порядке) были:

  • IntelliTrace не поддерживается в x64. Итак, одна из самых крутых новинок функции не будут работать в x64 Windows для Любые CPU проекты.

  • EXE-файлы x64 работают медленнее в Windows x64, чем EXE-файлы x86. Итак, идея x86 отладка, выпуск x64 будет означать, что «Оптимизированные» сборки в Release будут на самом деле работают хуже.

  • Жалобы клиентов при развертывании приложения и обнаружении, что оно не работает, хотя он работал на их машина.Они часто были рядом P / Invoke, но есть много других предположения, которые могут быть сделаны в приложение, которое может сломаться при запуске с разной разрядностью.

Вышеуказанные причины в сочетании с факт, что любой процессор не приносит преимущества (то есть вы фактически не можете получить преимущество расширенного адреса пространство, потому что EXE все еще может работать на x86) была причиной того, что по умолчанию был переключен.

У Рика Байерса отличный пост по этой теме здесь .

27
ответ дан 29 November 2019 в 04:46
поделиться

Я согласен с ошибками в тесте.

  • Это слишком коротко.
  • Как указывалось ранее, различные JIT для x86 / x64, вероятно, по-разному оптимизируют цикл.
  • На самом деле он проверяет только те переменные стека, которые, скорее всего, связаны с быстрым доступом к регистрам. Более реальный тест должен, по крайней мере, переместить доступ к адресному пространству.

Большую часть дополнительного времени, вероятно, занимает уровень WoW в случаях x86. Однако присущая процессу x64 неэффективность, скорее всего, перевесит накладные расходы уровня WoW в более длительном тесте, который фактически затрагивает память. Фактически, если бы тест был для доступа к памяти (путем создания и доступа к объектам в куче), вы бы увидели преимущества оптимизации указателя слоев WoW.

5
ответ дан 29 November 2019 в 04:46
поделиться

Я считаю, что ваш эталон несовершенен. IL-код из VS 2008 и VS 2010 для вашего примера программы идентичен в режиме выпуска (VS 2008 нацелен на .NET 2.0, а VS 2010 на .NET 4.0 с настройками по умолчанию). Поэтому вы не должны увидеть разницу в таймингах между VS 2008 и VS 2010. Оба компилятора выдают следующий код:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       69 (0x45)
  .maxstack  2
  .locals init ([0] class [System]System.Diagnostics.Stopwatch sw,
           [1] int32 i,
           [2] valuetype [mscorlib]System.TimeSpan elapsed)
  IL_0000:  call       class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::GetCallingAssembly()
  IL_0005:  callvirt   instance string [mscorlib]System.Reflection.Assembly::get_ImageRuntimeVersion()
  IL_000a:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_000f:  newobj     instance void [System]System.Diagnostics.Stopwatch::.ctor()
  IL_0014:  stloc.0
  IL_0015:  ldloc.0
  IL_0016:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Reset()
  IL_001b:  ldloc.0
  IL_001c:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Start()
  IL_0021:  ldc.i4.0
  IL_0022:  stloc.1
  IL_0023:  br.s       IL_0029
  IL_0025:  ldloc.1
  IL_0026:  ldc.i4.1
  IL_0027:  add
  IL_0028:  stloc.1
  IL_0029:  ldloc.1
  IL_002a:  ldc.i4     0x3b9aca00
  IL_002f:  blt.s      IL_0025
  IL_0031:  ldloc.0
  IL_0032:  callvirt   instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
  IL_0037:  stloc.2
  IL_0038:  ldloc.2
  IL_0039:  box        [mscorlib]System.TimeSpan
  IL_003e:  call       void [mscorlib]System.Console::WriteLine(object)
  IL_0043:  br.s       IL_0015
} // end of method Program::Main

Единственное, что может отличаться - это целевая платформа. VS 2010 использует x86 в качестве целевой платформы по умолчанию, тогда как VS 2008 использует AnyCPU. Если вы работаете на 64-битной системе, это приведет к тому, что для сборок VS 2008 и VS 2010 будут использоваться разные JIT-компиляторы. Это может привести к различным результатам, поскольку JIT-компиляторы разрабатываются отдельно.

8
ответ дан 29 November 2019 в 04:46
поделиться

У нас та же проблема. После преобразования проекта wpf из .NET 3.5 (VS2008) в .NET 4 (VS2010) графический интерфейс стал намного менее отзывчивым (почти 1 секунда задержки для каждого щелчка).

После некоторого расследования мы пришли к выводу, что это связано с тем, что Visual Studio 2010 потребляет гораздо больше ресурсов и все работает медленнее, когда мы убираем из VS2010. Когда мы запускаем собранный проект как .exe, он снова запускается быстро.

0
ответ дан 29 November 2019 в 04:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: