Оптимизация кода
От: Аноним  
Дата: 20.04.05 07:16
Оценка:
Выполняет ли JIT оптимизацию IL-кода, или все компилится один к одному?
Re: Оптимизация кода
От: GarryIV  
Дата: 20.04.05 07:34
Оценка:
Hello, !

> Выполняет ли JIT оптимизацию IL-кода, или все компилится один к одному?


Что то делает...

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/fastmanagedcode.asp

The Just-in-Time compiler

...
Unlike a traditional off-line C++ compilation process, the time spent in the JIT compiler is a "wall clock time" delay, in each user's face, so the JIT compiler does not have the luxury of exhaustive optimization passes. Even so, the list of optimizations the JIT compiler performs is impressive:

Constant folding
Constant and copy propagation
Common subexpression elimination
Code motion of loop invariants
Dead store and dead code elimination
Register allocation
Method inlining
Loop unrolling (small loops with small bodies)

Posted via RSDN NNTP Server 1.9
WBR, Igor Evgrafov
Re[2]: Оптимизация кода
От: Аноним  
Дата: 20.04.05 07:46
Оценка: -1
Здравствуйте, GarryIV, Вы писали:

GIV>Hello, !


>> Выполняет ли JIT оптимизацию IL-кода, или все компилится один к одному?


GIV>Что то делает...


GIV>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/fastmanagedcode.asp


GIV>

GIV>The Just-in-Time compiler

GIV>...
GIV>Unlike a traditional off-line C++ compilation process, the time spent in the JIT compiler is a "wall clock time" delay, in each user's face, so the JIT compiler does not have the luxury of exhaustive optimization passes. Even so, the list of optimizations the JIT compiler performs is impressive:

GIV>Constant folding
GIV>Constant and copy propagation
GIV>Common subexpression elimination
GIV>Code motion of loop invariants
GIV>Dead store and dead code elimination
GIV>Register allocation
GIV>Method inlining
GIV>Loop unrolling (small loops with small bodies)


Спасибо. Просто мне кажется где-то пробегала такая тема,
что вот такой код
ArrayList ar = new ArrayList();
for(int i = 0; i < ar.Count; i++)
{
   ar[i] = ...;
}


будет компилятором оптимизирован в такой

ArrayList ar = new ArrayList();
int count = ar.Count;
for(int i = 0; i < count; i++)
{
   ar[i] = ...;
}


Дык вот в IL-е ничего подобного я не заметил. Идет как и положено постоянно ображение к get_Count()
Re[3]: Оптимизация кода
От: GarryIV  
Дата: 20.04.05 08:12
Оценка:
Hello, !

GIV>> Что то делает...


GIV>> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/fastmanagedcode.asp


GIV>>

GIV>> Constant folding
GIV>> Constant and copy propagation
GIV>> Common subexpression elimination
GIV>> Code motion of loop invariants
GIV>> Dead store and dead code elimination
GIV>> Register allocation
GIV>> Method inlining
GIV>> Loop unrolling (small loops with small bodies)


> Спасибо. Просто мне кажется где-то пробегала такая тема,

> что вот такой код
>
 > ArrayList ar = new ArrayList();
 > for(int i = 0; i < ar.Count; i++)
 > {
 >    ar[i] = ...;
 > }
 >


> будет компилятором оптимизирован в такой


>
 > ArrayList ar = new ArrayList();
 > int count = ar.Count;
 > for(int i = 0; i < count; i++)
 > {
 >    ar[i] = ...;
 > }
 >


> Дык вот в IL-е ничего подобного я не заметил. Идет как и положено

> постоянно ображение к get_Count()

Чтоб понять что наоптимизировал JIT Comiler надо смотреть native код, который он порождает (как это сделать я не знаю). В принципе этот пример попадает под "Code motion of loop invariants" но будет ли реально это сделано я не берусь утверждать. Сделай тесты — посмотри.
Posted via RSDN NNTP Server 1.9
WBR, Igor Evgrafov
Re[4]: Оптимизация кода
От: Аноним  
Дата: 20.04.05 08:35
Оценка: +1
Как он может в это оптимизировать? А если я сделаю al.Add() в цикле, что, всё сломается?
Re[5]: Оптимизация кода
От: Аноним  
Дата: 20.04.05 08:42
Оценка: -1
А>Как он может в это оптимизировать? А если я сделаю al.Add() в цикле, что, всё сломается?

ты блин еще рекурсию бесконечно-вложенную сделай и спроси потом сломается ли она или нет
Re[3]: Оптимизация кода
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 20.04.05 08:46
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Спасибо. Просто мне кажется где-то пробегала такая тема,

А>что вот такой код
А>будет компилятором оптимизирован в такой
А>Дык вот в IL-е ничего подобного я не заметил. Идет как и положено постоянно ображение к get_Count()

Все правильно. Вычисление того, является ли get_Count() инвариантом в цикле, в общем случае невозможно. Поэтому и не происходит вынос инварианта из цикла.
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[4]: Оптимизация кода
От: Andir Россия
Дата: 20.04.05 08:46
Оценка: 10 (1) +2
Здравствуйте, GarryIV, Вы писали:

GIV>Чтоб понять что наоптимизировал JIT Comiler надо смотреть native код, который он порождает (как это сделать я не знаю).


cordbg.exe идущий в SDK.

С Уважением, Andir!
using(RSDN@Home 1.1.4 beta 3){/* Работаем! */}
Re[4]: Оптимизация кода
От: GlebZ Россия  
Дата: 20.04.05 15:50
Оценка:
Здравствуйте, xvost, Вы писали:

X>Все правильно. Вычисление того, является ли get_Count() инвариантом в цикле, в общем случае невозможно. Поэтому и не происходит вынос инварианта из цикла.

На уровне компиляции JIT многое другое возможно. Например inlining get_Count. Я не особо помню, подсчитывает ли он в рантайме количество (по моему да), так что весьма вероятно преобразование в ссылку на значение.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re: Оптимизация кода
От: oleg542  
Дата: 20.04.05 19:53
Оценка: :)
Здравствуйте, Аноним, Вы писали:
А>Выполняет ли JIT оптимизацию IL-кода, или все компилится один к одному?
Если в методе используются поля обьектов, то создаются локальные переменные и инициализируются этими полями. Потом работа идёт через них (в этом случае экономится один push).
P.S. смотри в рефлекторе.
Re[2]: Оптимизация кода
От: Lloyd Россия  
Дата: 21.04.05 07:59
Оценка: +1
Здравствуйте, oleg542, Вы писали:

А>>Выполняет ли JIT оптимизацию IL-кода, или все компилится один к одному?

O>Если в методе используются поля обьектов, то создаются локальные переменные и инициализируются этими полями. Потом работа идёт через них (в этом случае экономится один push).
O>P.S. смотри в рефлекторе.

Результат работы jit-а в рефлекторе? Оригинально.
... << RSDN@Home 1.1.4 beta 6 rev. 422>>
Re[3]: Оптимизация кода
От: Аноним  
Дата: 20.04.05 08:21
Оценка: -1
Судя по результатом тестов, про которые я читал (результаты сравнения различных компиляторов), это делается. А "бесполезные" циклы, вообще, удаляются.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[3]: Оптимизация кода
От: Аноним  
Дата: 20.04.05 08:46
Оценка:
чтоб смотреть натив релиза надо сделать делние но 0 в том месте где ты хочешь тормознуть прогу, после этого он тебе предложет посмотреть дизасембли, а если не покажет то заходишь в дебуг и сам его включаеш.
---------------------
Ты можеш все ибо все есть в тебе.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[4]: Оптимизация кода
От: Аноним  
Дата: 20.04.05 20:21
Оценка: -1
> cordbg.exe идущий в SDK.
Зачем? В VS2002-2003 (7.0-7.1) cтавишь break-point на то место где хочешь посмотреть исходный код, лезешь в меню Debug->Windows->Disassembly, открываешь появившуюся страницу и смотришь native код.
Любое сложное решение — проявление лени человека, которому это поручили


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[4]: Оптимизация кода
От: Аноним  
Дата: 21.04.05 03:52
Оценка:
QuICE
Оптимизированный код тяжел для исследования?
---------------------
Ты можеш все ибо все есть в тебе.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[5]: Оптимизация кода
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.04.05 16:03
Оценка:
Здравствуйте, QuICE, Вы писали:

>> cordbg.exe идущий в SDK.

QIC>Зачем? В VS2002-2003 (7.0-7.1) cтавишь break-point на то место где хочешь посмотреть исходный код, лезешь в меню Debug->Windows->Disassembly, открываешь появившуюся страницу и смотришь native код.

Для запускаемого под отладчиком приложение принципиально не генерируется оптимальный код. Так что или пытаться приатачиться студией на ходу (с бабушка надвое предсказанным результатом), или cordbg.exe.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Оптимизация кода
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.04.05 16:03
Оценка:
Здравствуйте, xvost, Вы писали:

X>Все правильно. Вычисление того, является ли get_Count() инвариантом в цикле, в общем случае невозможно. Поэтому и не происходит вынос инварианта из цикла.


Вообще-то более чем возможно. Просто оптимизатор халявит.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Оптимизация кода
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.04.05 16:03
Оценка: -1
Здравствуйте, Corwin_XX, Вы писали:

C_X>Судя по результатом тестов, про которые я читал (результаты сравнения различных компиляторов), это делается. А "бесполезные" циклы, вообще, удаляются.


"Не читайте советских газет перед едой." (с)
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Оптимизация кода
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.04.05 16:03
Оценка: -1
Здравствуйте, <Аноним>, Вы писали:

А>Как он может в это оптимизировать? А если я сделаю al.Add() в цикле, что, всё сломается?


И тем не менее при наличии хорошего оптимизатора подобная оптимизация возможна. К сожалению, подобные оптимизации не делаются даже с массивами и в foreach-ах. А уж там им ни что не препятствует.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Оптимизация кода
От: Igor Trofimov  
Дата: 24.04.05 16:47
Оценка:
VD>И тем не менее при наличии хорошего оптимизатора подобная оптимизация возможна. К сожалению, подобные оптимизации не делаются даже с массивами и в foreach-ах. А уж там им ни что не препятствует.

здесь
Re[5]: Агащазкакже
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 25.04.05 05:51
Оценка:
Здравствуйте, VladD2, Вы писали:

X>>Все правильно. Вычисление того, является ли get_Count() инвариантом в цикле, в общем случае невозможно. Поэтому и не происходит вынос инварианта из цикла.

VD>Вообще-то более чем возможно. Просто оптимизатор халявит.

Вот кусок кода:


class C
{
  private ArrayList myList;
  public C(ArrayList list) {myList = list;}
  public void foo() {myList.Add(1);}
}

......
ArrayList list = new ArrayList (collection);
C c = new C(list);
for (int i=0; i<list.Count(); i++)
  c.foo();


И как тут оптимизатор будет думать????
list.Count() не является инвариантом в этом цикле
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[6]: Агащазкакже
От: qxWork Голландия http://www.jetbrains.com/company/people/Coox_Sergey.html
Дата: 25.04.05 06:06
Оценка:
X>Вот кусок кода:


X>
X>class C
X>{
X>  private ArrayList myList;
X>  public C(ArrayList list) {myList = list;}
X>  public void foo() {myList.Add(1);}
X>}

X>......
X>ArrayList list = new ArrayList (collection);
X>C c = new C(list);
X>for (int i=0; i<list.Count(); i++)
X>  c.foo();
X>


X>И как тут оптимизатор будет думать????

X>list.Count() не является инвариантом в этом цикле

Это следствие отсутствия в .NET модификатора const. С++ оптимизатор лего справляется с конструкциями вида:
class C {
  int Count() const;
  void foo() const; 
}

void Foo( C &c ) {
  
  for( int i=0; i<c.Count(); ++i ) {
    c.foo();
  }
}

Более того, если добавить в класс C mutable поле и модифицировать его внутри foo, то можно наблюдать интересный эффект

Возвращаясь к опримизатору IL, кое-что он все-таки оптимизит, например, утверждается, что код
int []a = new int[100];
for( int i=0; i<a.Length; ++i ) {
  a[i] = i;
}


работает быстрее, чем
int []a = new int[100];
int nItems = a.Length;
for( int i=0; i<nItems; ++i ) {
  a[i] = i;
}


вследствие того, что оптимизатор удаляет проверки границ массива. Убил бы )
Re[3]: Оптимизация кода
От: SiAVoL Россия  
Дата: 25.04.05 07:05
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Спасибо. Просто мне кажется где-то пробегала такая тема,

А>что вот такой код
А>
А>ArrayList ar = new ArrayList();
А>for(int i = 0; i < ar.Count; i++)
А>{
А>   ar[i] = ...;
А>}
А>


А>будет компилятором оптимизирован в такой


А>
А>ArrayList ar = new ArrayList();
А>int count = ar.Count;
А>for(int i = 0; i < count; i++)
А>{
А>   ar[i] = ...;
А>}
А>


А>Дык вот в IL-е ничего подобного я не заметил. Идет как и положено постоянно ображение к get_Count()

буквально только сегодня прочитал в блоге Brad Abrams`а (здесь) про оптимизацию такого случая.
Если вкратце, то первый вариант будет работать даже медленнее чем второй. Происходит из-за того что JIT должен проводить проверку выхода за пределы массива. Так вот во втором случае он распознает паттерн перебора массива и проверку производит только один раз. А во втором на каждой итерации.
Мораль такова, не стоит пытаться перехитрить оптимизатор, писать надо естесственным образом, а уж он разберется что к чему. К тому же он постоянно развивается. Например в том же блоге написано, что и первый вариант со временем тоже возможно будет распознаваться.
... << RSDN@Home 1.1.4 beta 5 rev. 0>>
Re[6]: Агащазкакже
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.04.05 11:43
Оценка:
Здравствуйте, xvost, Вы писали:

X>
X>class C
X>{
X>  private ArrayList myList;
X>  public C(ArrayList list) {myList = list;}
X>  public void foo() {myList.Add(1);}
X>}

X>......
X>ArrayList list = new ArrayList (collection);
X>C c = new C(list);
X>for (int i=0; i<list.Count(); i++)
X>  c.foo();
X>


X>И как тут оптимизатор будет думать????

X>list.Count() не является инвариантом в этом цикле

Тут — никак. Но это не означает, что невозможно распозновать случае которые не вызывают модифицирующие методы. Особенно это полезно для встроенных коллекций которые используются очень часто. Подобная оптимизация могла бы неплохо ускорить код приложений.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Агащазкакже
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.04.05 11:43
Оценка:
Здравствуйте, qxWork, Вы писали:

W>Это следствие отсутствия в .NET модификатора const.


Подобный модификатор дотнету не нужен. В дотнете можно читать IL. Это позволяет определить наличие побочных эффектов без дополнительной помощь. К сожалению разработчики дотнета не озаботились подобными проблемами. Но в будущем, я уверен, до этого обязательно дойдет дело.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Оптимизация кода
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.04.05 11:43
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:

VD>>И тем не менее при наличии хорошего оптимизатора подобная оптимизация возможна. К сожалению, подобные оптимизации не делаются даже с массивами и в foreach-ах. А уж там им ни что не препятствует.


iT>здесь


Предпочитаю практику .

Ниже приведен набор тестов для второго фрэймворка.

1. Тест List<int> с выносом длинны в перемнную.
            Console.WriteLine("Framework Version: " + Environment.Version);

            const int count = 10000;
            List<int> array = new List<int>(count);

            for (int i = 0; i < count; i++)
                array.Add(i % 20);

            Console.WriteLine("Start");

            int start = Environment.TickCount;

            int sum = 0;

            int len = array.Count;

            for (int k = 0; k < 100000; k++)
                for (int i = 0; i < len; i++)
                    sum += array[i];

            Console.WriteLine("Time is {0}, sum = {1}", 
                Environment.TickCount - start, sum);

Результат:
Framework Version: 2.0.50215.44
Start
Time is 2719, sum = 910065408

2. Тест List<int> с проверкой длинны внутри цикла.
            Console.WriteLine("Framework Version: " + Environment.Version);

            const int count = 10000;
            List<int> array = new List<int>(count);

            for (int i = 0; i < count; i++)
                array.Add(i % 20);

            Console.WriteLine("Start");

            int start = Environment.TickCount;

            int sum = 0;

            for (int k = 0; k < 100000; k++)
                for (int i = 0; i < array.Count; i++)
                    sum += array[i];

            Console.WriteLine("Time is {0}, sum = {1}", 
                Environment.TickCount - start, sum);

Framework Version: 2.0.50215.44
Start
Time is 2250, sum = 910065408

3. С копрированием в масси и проверкой длинны массива внутри цикла.
            Console.WriteLine("Framework Version: " + Environment.Version);

            const int count = 10000;
            List<int> array1 = new List<int>(count);

            for (int i = 0; i < count; i++)
                array1.Add(i % 20);

            Console.WriteLine("Start");

            int start = Environment.TickCount;

            int sum = 0;

            int len = array1.Count;
            int[] array = array1.ToArray();

            for (int k = 0; k < 100000; k++)
                for (int i = 0; i < array.Length; i++)
                    sum += array[i];

            Console.WriteLine("Time is {0}, sum = {1}", 
                Environment.TickCount - start, sum);

Framework Version: 2.0.50215.44
Start
Time is 1359, sum = 910065408

4. С копрированием в масси и выносом длинны в переменную.
            Console.WriteLine("Framework Version: " + Environment.Version);

            const int count = 10000;
            List<int> array1 = new List<int>(count);

            for (int i = 0; i < count; i++)
                array1.Add(i % 20);

            Console.WriteLine("Start");

            int start = Environment.TickCount;

            int sum = 0;

            int len = array1.Count;
            int[] array = array1.ToArray();

            for (int k = 0; k < 100000; k++)
                for (int i = 0; i < len; i++)
                    sum += array[i];

            Console.WriteLine("Time is {0}, sum = {1}", 
                Environment.TickCount - start, sum);

Framework Version: 2.0.50215.44
Start
Time is 1359, sum = 910065408

5. На чистом массиве с выносом длинны в переменную:
            Console.WriteLine("Framework Version: " + Environment.Version);

            const int count = 10000;
            int [] array = new int[count];

            for (int i = 0; i < count; i++)
                array[i] = i % 20;

            Console.WriteLine("Start");

            int start = Environment.TickCount;

            int sum = 0;

            int len = array.Length;

            for (int k = 0; k < 100000; k++)
                for (int i = 0; i < len; i++)
                    sum += array[i];

            Console.WriteLine("Time is {0}, sum = {1}", 
                Environment.TickCount - start, sum);

Framework Version: 2.0.50215.44
Start
Time is 1344, sum = 910065408

6. На чистом массиве с проверкой длинны в цикле:
            Console.WriteLine("Framework Version: " + Environment.Version);

            const int count = 10000;
            int [] array = new int[count];

            for (int i = 0; i < count; i++)
                array[i] = i % 20;

            Console.WriteLine("Start");

            int start = Environment.TickCount;

            int sum = 0;

            int len = array.Length;

            for (int k = 0; k < 100000; k++)
                for (int i = 0; i < array.Length; i++)
                    sum += array[i];

            Console.WriteLine("Time is {0}, sum = {1}", 
                Environment.TickCount - start, sum);

Framework Version: 2.0.50215.44
Start
Time is 906, sum = 910065408


Вызов свойства Count точно менее выгодно нежели копирование его значения в переменную. А вот с массивом все не так очевидно. Можно смело Сказать, что для второго фрэймворка проверка длинны массива не является проблемой и не требует оптимизации. В то время как проверка длинны коллекции более затратная операция.

Однако все это такие милиметры, что ловить их в большинстве случаев смысла не имеет.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Агащазкакже
От: Аноним  
Дата: 25.04.05 12:45
Оценка:
интересно, как это нет const??? или что то другое под этим подразумеваеться?
--------------------------------
Авто-подпись — дешевый понт!


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[8]: Агащазкакже
От: qxWork Голландия http://www.jetbrains.com/company/people/Coox_Sergey.html
Дата: 25.04.05 12:52
Оценка:
W>>Это следствие отсутствия в .NET модификатора const.
VD>Подобный модификатор дотнету не нужен. В дотнете можно читать IL. Это позволяет определить наличие побочных эффектов без дополнительной помощь. К сожалению разработчики дотнета не озаботились подобными проблемами. Но в будущем, я уверен, до этого обязательно дойдет дело.
К сожалению, анализ IL очень дорог, чтобы его использовать в оптимизации. Использовать слово const значительно проще и быстрее, да и код становится читабельнее в разы.
Re[8]: Агащазкакже
От: qxWork Голландия http://www.jetbrains.com/company/people/Coox_Sergey.html
Дата: 25.04.05 12:53
Оценка:
YNN>интересно, как это нет const??? или что то другое под этим подразумеваеться?
Модификатора const у методов и параметров действительно нет в .NET
Re[9]: Агащазкакже
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.04.05 15:06
Оценка:
Здравствуйте, qxWork, Вы писали:

W>К сожалению, анализ IL очень дорог, чтобы его использовать в оптимизации. Использовать слово const значительно проще и быстрее, да и код становится читабельнее в разы.


Ну, на счет читабельности С++-ного кода я бы лучше помолчал.

А что до родоговизны... Он один фиг читается. Иначе все инлайнинги и т.п. были бы просто не возвожны. К тому же метод можно один раз ататически анализировать и добавлять ему атрибут. А в дальнейшем анализировать только его.

В общем, это более чем реально. Но создатели дотнета не сделали этого. Будем надеяться что только пока.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.