JIT-компилятор лажает?
От: bitferens  
Дата: 19.06.09 07:03
Оценка:
Тема тысячи раз обсуждалась, но тем не менее.
Насколько оптимизирующий JIT-компилятор оптимизирует?
К примеру, весь цивилизованный мир уверяет, что тривиальные свойства инлайнятся, и я до недавнего времени был уверен, что в большинстве случаев это так. Но после странных скачков производительности в проекте решил-таки проверить. Имеется класс с целочисленным свойством и полем:



    class PropertyTest
    {

        public long Field;

        public long Property
        {
            get
            {
                return Field;
            }
            set
            {
                Field = value;
            }
        }
    }


В цикле суммируем числа от 0 до N — 1 сначала через поле, а затем через свойство:



        static void Main(string[] args)
        {
            var test = new PropertyTest();
            
            const long N = 10000000;
            
            var sum = 0L;
            var start = DateTime.Now;

            for (int i = 0; i < N; ++i)
            {
                test.Field = i;
                sum += test.Field;
            }

            var period = DateTime.Now - start;

            Console.WriteLine("Ticks: {0}, Sum: {1}", period.Ticks, sum);

            sum = 0;
            start = DateTime.Now;

            for (int i = 0; i < N; ++i)
            {
                test.Property = i;
                sum += test.Property;
            }

            period = DateTime.Now - start;

            Console.WriteLine("Ticks: {0}, Sum: {1}", period.Ticks, sum);
            Console.ReadKey(true);
        }


На моей машине (C2D 2.5GHz/Vista/.NET 3.5 SP1) выигрыш при использовании поля получается чуть ли не в 5 раз.

Вопрос: как понимать результаты подобной оптимизации?
c# jit оптимизация inline
Re: JIT-компилятор лажает?
От: Aen Sidhe Россия Просто блог
Дата: 19.06.09 07:12
Оценка:
Здравствуйте, bitferens, Вы писали:

B>На моей машине (C2D 2.5GHz/Vista/.NET 3.5 SP1) выигрыш при использовании поля получается чуть ли не в 5 раз.


B>Вопрос: как понимать результаты подобной оптимизации?


Сразу же будет вопрос: какой компилятор, какой режим компиляции (дебаг/релиз), как запускал, какие настройки компиляции.
С уважением, Анатолий Попов.
ICQ: 995-908
Re: JIT-компилятор лажает?
От: Александр Кузнецов Россия  
Дата: 19.06.09 07:25
Оценка: +1
Здравствуйте, bitferens, Вы писали:

B>На моей машине (C2D 2.5GHz/Vista/.NET 3.5 SP1) выигрыш при использовании поля получается чуть ли не в 5 раз.


B>Вопрос: как понимать результаты подобной оптимизации?


Есть мнение, что компиляция была в режиме DEBUG (5-10 раз довольно характерные цифры). В этом режиме JIT не использует Inline, так как на свойства могут быть поставлены брякпоинты, и тогда отладка свойств может стать вещью довольно геморной. В Release режиме время работы примерно одинаковое.

Вот если Release стоял — тогда это повод очень хорошо задуматься.
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
Re[2]: JIT-компилятор лажает?
От: bitferens  
Дата: 19.06.09 07:28
Оценка: :)
Здравствуйте, Aen Sidhe, Вы писали:

Компилятор? Хм... Вроде как указал — 3.5. Если быть точным — 3.5.30729.1)

Запускал конечно в релизе, через студию, в дебаге чудес не жду).
Оптимизация в релизе естественно включена.


AS>Здравствуйте, bitferens, Вы писали:


B>>На моей машине (C2D 2.5GHz/Vista/.NET 3.5 SP1) выигрыш при использовании поля получается чуть ли не в 5 раз.


B>>Вопрос: как понимать результаты подобной оптимизации?


AS>Сразу же будет вопрос: какой компилятор, какой режим компиляции (дебаг/релиз), как запускал, какие настройки компиляции.
Re[3]: JIT-компилятор лажает?
От: _FRED_ Черногория
Дата: 19.06.09 07:31
Оценка: +1
Здравствуйте, bitferens, Вы писали:

B>Запускал конечно в релизе, через студию, в дебаге чудес не жду).

B>Оптимизация в релизе естественно включена.

Запусти не через студию. Перед этим прогони сборку через NGen.
Help will always be given at Hogwarts to those who ask for it.
Re[4]: JIT-компилятор лажает?
От: _FRED_ Черногория
Дата: 19.06.09 07:57
Оценка: 1 (1)
Здравствуйте, _FRED_, Вы писали:

_FR>Запусти не через студию. Перед этим прогони сборку через NGen.


У меня вот такие результаты этих вот тестов:

using System;
using System.Diagnostics;

class PropertyTest
{
  public long Field;

  public long Property {
    get { return Field; }
    set { Field = value; }
  }
}

static class Program
{
  static long TestField(PropertyTest instance, long tests) {
    var sum = 0L;
    for(var i = 0L; i < tests; i++) {
      instance.Field = i;
      sum += instance.Field;
    }//for
    return sum;
  }

  static long TestProperty(PropertyTest instance, long tests) {
    var sum = 0L;
    for(var i = 0L; i < tests; i++) {
      instance.Property = i;
      sum += instance.Property;
    }//for
    return sum;
  }

  static void Test(long tests, Func<PropertyTest, long, long> test) {
    var instance = new PropertyTest();
    var stopwatch = Stopwatch.StartNew();
    var sum = test(instance, tests);
    stopwatch.Stop();
    Console.WriteLine("Ticks: {0}, Sum: {1}", stopwatch.ElapsedTicks, sum);
  }

  static void Main(string[] args) {
    TestField(new PropertyTest(), 10);
    TestProperty(new PropertyTest(), 10);

    Console.WriteLine("Environment.Version = {0}:", Environment.Version);

    long testsCount;
    if(args == null || args.Length != 1 || !Int64.TryParse(args[0], out testsCount)) {
      testsCount = 10000000L;
    }//if
    Console.WriteLine("Tests Count: {0}", testsCount);

    Console.Write("[TestField]:\t");
    Test(testsCount, TestField);
    Console.Write("[TestProperty]:\t");
    Test(testsCount, TestProperty);

    Console.ReadKey(true);
  }
}


Environment.Version = 2.0.50727.3082:
Tests Count: 10000000
[TestField]:    Ticks: 133183098, Sum: 49999995000000
[TestProperty]: Ticks: 132275034, Sum: 49999995000000


Environment.Version = 4.0.20506.1:
Tests Count: 10000000
[TestField]:    Ticks: 131498505, Sum: 49999995000000
[TestProperty]: Ticks: 131230197, Sum: 49999995000000


ИМХО, свойства рулят (ну, скорее всего будут рулить в следующем фреймворке), как это ни удивительно
Help will always be given at Hogwarts to those who ask for it.
Re[5]: JIT-компилятор лажает?
От: maybeleo  
Дата: 19.06.09 08:13
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Запусти не через студию.


да, все дело в этом

_FR>Перед этим прогони сборку через NGen.


а это лишнее. При запуске не из студии результаты, действительно, идентичные
Re[5]: JIT-компилятор лажает?
От: Pavel Dvorkin Россия  
Дата: 19.06.09 08:36
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, _FRED_, Вы писали:


_FR>>Запусти не через студию. Перед этим прогони сборку через NGen.


_FR>У меня вот такие результаты этих вот тестов:


<skipped, тест без изменений>

Environment.Version = 2.0.50727.3053:
Tests Count: 10000000
[TestField]: Ticks: 197140, Sum: 49999995000000
[TestProperty]: Ticks: 225414, Sum: 49999995000000

VS2008, Athlon 4200+ Dual

Меня в твоем сообщении числа удивляют. Что за сотня миллионов тиков ? Чему у тебя равен Stopwatch.Frequency ? У меня 3579545.
With best regards
Pavel Dvorkin
Re[6]: JIT-компилятор лажает?
От: Pavel Dvorkin Россия  
Дата: 19.06.09 08:37
Оценка:
P.S Запускал через FAR
With best regards
Pavel Dvorkin
Re[6]: JIT-компилятор лажает?
От: samius Япония http://sams-tricks.blogspot.com
Дата: 19.06.09 08:48
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>[TestField]: Ticks: 197140, Sum: 49999995000000

PD>[TestProperty]: Ticks: 225414, Sum: 49999995000000

PD>VS2008, Athlon 4200+ Dual


PD>Меня в твоем сообщении числа удивляют. Что за сотня миллионов тиков ? Чему у тебя равен Stopwatch.Frequency ? У меня 3579545.


Видимо речь идет о GetTickCount, который возвращает

The return value is the number of milliseconds that have elapsed since the system was started.

Причем тут Stopwatch.Frequency?
Re[7]: JIT-компилятор лажает?
От: samius Япония http://sams-tricks.blogspot.com
Дата: 19.06.09 08:50
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>[TestField]: Ticks: 197140, Sum: 49999995000000

PD>>[TestProperty]: Ticks: 225414, Sum: 49999995000000

PD>>VS2008, Athlon 4200+ Dual


PD>>Меня в твоем сообщении числа удивляют. Что за сотня миллионов тиков ? Чему у тебя равен Stopwatch.Frequency ? У меня 3579545.


S>Причем тут Stopwatch.Frequency?


А, ну видимо в исходном коде были тики, а _FRED_ померил через Stopwatch, а обозначения оставил...
Re[4]: JIT-компилятор лажает?
От: bitferens  
Дата: 19.06.09 09:12
Оценка:
Большое спасибо, я знал, что истина где-то рядом.

Правда теперь не очень понятны две вещи:

1. Почему не идентичны результаты запусков релиза из консоли и студии?

2. Можно ли доверять ассемблерному листингу, который выдает студия?

Присваивание поля транслируется так (в релизе):

            {
                test.Field = i;



  mov         eax,dword ptr [ebp-20h] 
  cdq              
  mov         ecx,dword ptr [ebp+FFFFFF74h] 
  mov         dword ptr [ecx+4],eax 
  mov         dword ptr [ecx+8],edx


А присваивание свойства так:

            {
                test.Property = i;



  mov         eax,dword ptr [ebp-2Ch] 
  cdq              
  push        edx  
  push        eax  
  mov         ecx,dword ptr [ebp+FFFFFF74h] 
  cmp         dword ptr [ecx],ecx 
  call        dword ptr ds:[000F9DC4h]


Видно, что присваивание свойства выливается в косвенный вызов. Хотя, судя по времени выполнения (не из студии), его быть не должно.
Есть ли какая-то возможность посмотреть, что реально генерирует JIT-компилятор?



Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, bitferens, Вы писали:


B>>Запускал конечно в релизе, через студию, в дебаге чудес не жду).

B>>Оптимизация в релизе естественно включена.

_FR>Запусти не через студию. Перед этим прогони сборку через NGen.
Re[6]: JIT-компилятор лажает?
От: _FRED_ Черногория
Дата: 19.06.09 09:16
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>[TestField]: Ticks: 197140, Sum: 49999995000000

PD>[TestProperty]: Ticks: 225414, Sum: 49999995000000
PD>VS2008, Athlon 4200+ Dual

PD>Меня в твоем сообщении числа удивляют. Что за сотня миллионов тиков ? Чему у тебя равен Stopwatch.Frequency ? У меня 3579545.


Stopwatch.Frequency = 3003410000


OS NameMicrosoft Windows XP Professional
Version5.1.2600 Service Pack 3 Build 2600
ProcessorIntel Core2Duo CPU E8400 @ 3.00GHz
Processorx86 Family 6 Model 23 Stepping 6 GenuineIntel ~3003 Mhz
Hardware Abstraction LayerVersion = "5.1.2600.5512 (xpsp.080413-2111)"
Total Physical Memory4,096.00 MB
Help will always be given at Hogwarts to those who ask for it.
Re[5]: JIT-компилятор лажает?
От: _FRED_ Черногория
Дата: 19.06.09 09:18
Оценка:
Здравствуйте, bitferens, Вы писали:

B>2. Можно ли доверять ассемблерному листингу, который выдает студия?


Если запустить приложение самостоятельно, а потом уже подключить к приложению отладчик, то доверять можно.
Help will always be given at Hogwarts to those who ask for it.
Re[8]: JIT-компилятор лажает?
От: _FRED_ Черногория
Дата: 19.06.09 09:21
Оценка:
Здравствуйте, samius, Вы писали:

S>А, ну видимо в исходном коде были тики, а _FRED_ померил через Stopwatch, а обозначения оставил...


Да нет, вывод адекватен коду (я сначала запостил различающиеся — в коде не выводился "Tests Count", но удалил то сообщение и переписал)
Help will always be given at Hogwarts to those who ask for it.
Re[7]: JIT-компилятор лажает?
От: Pavel Dvorkin Россия  
Дата: 19.06.09 09:34
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>[TestField]: Ticks: 197140, Sum: 49999995000000

PD>>[TestProperty]: Ticks: 225414, Sum: 49999995000000
PD>>VS2008, Athlon 4200+ Dual

PD>>Меня в твоем сообщении числа удивляют. Что за сотня миллионов тиков ? Чему у тебя равен Stopwatch.Frequency ? У меня 3579545.


_FR>
_FR>Stopwatch.Frequency = 3003410000
_FR>


Гм. Интересно, почему такие различия. Памяти у меня 2 Гб, процессор Dual 4200 т.е 2100 на ядро, правда, не Intel, а AMD. Странно. Просьба к тем, кто может — приведите свои данные для этого Stopwatch.Frequency.
With best regards
Pavel Dvorkin
Re[7]: JIT-компилятор лажает?
От: Pavel Dvorkin Россия  
Дата: 19.06.09 09:36
Оценка: :))
Здравствуйте, _FRED_, Вы писали:

Проверил на другой машине, тоже AMD, но Dual 3800+. Результат изумительный

Environment.Version = 2.0.50727.1433:
Tests Count: 10000000
[TestField]: Ticks: 1245633723, Sum: 49999995000000
[TestProperty]: Ticks: -1022111917, Sum: 49999995000000

Черт знает что.
With best regards
Pavel Dvorkin
Re[8]: JIT-компилятор лажает?
От: samius Япония http://sams-tricks.blogspot.com
Дата: 19.06.09 09:38
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, _FRED_, Вы писали:


PD>Проверил на другой машине, тоже AMD, но Dual 3800+. Результат изумительный


PD>Environment.Version = 2.0.50727.1433:

PD>Tests Count: 10000000
PD>[TestField]: Ticks: 1245633723, Sum: 49999995000000
PD>[TestProperty]: Ticks: -1022111917, Sum: 49999995000000

PD>Черт знает что.


А если повторить?
Re[9]: JIT-компилятор лажает?
От: Pavel Dvorkin Россия  
Дата: 19.06.09 09:50
Оценка:
Здравствуйте, samius, Вы писали:

S>А если повторить?


А я , думаешь, не повторял ?
With best regards
Pavel Dvorkin
Re[8]: JIT-компилятор лажает?
От: _FRED_ Черногория
Дата: 19.06.09 09:57
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Проверил на другой машине, тоже AMD, но Dual 3800+. Результат изумительный


PD>Черт знает что.

А фрекьюнси чему там равно?
Help will always be given at Hogwarts to those who ask for it.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.