Тема тысячи раз обсуждалась, но тем не менее.
Насколько оптимизирующий 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 раз.
Вопрос: как понимать результаты подобной оптимизации?
Здравствуйте, bitferens, Вы писали:
B>На моей машине (C2D 2.5GHz/Vista/.NET 3.5 SP1) выигрыш при использовании поля получается чуть ли не в 5 раз.
B>Вопрос: как понимать результаты подобной оптимизации?
Сразу же будет вопрос: какой компилятор, какой режим компиляции (дебаг/релиз), как запускал, какие настройки компиляции.
Здравствуйте, bitferens, Вы писали:
B>На моей машине (C2D 2.5GHz/Vista/.NET 3.5 SP1) выигрыш при использовании поля получается чуть ли не в 5 раз.
B>Вопрос: как понимать результаты подобной оптимизации?
Есть мнение, что компиляция была в режиме DEBUG (5-10 раз довольно характерные цифры). В этом режиме JIT не использует Inline, так как на свойства могут быть поставлены брякпоинты, и тогда отладка свойств может стать вещью довольно геморной. В Release режиме время работы примерно одинаковое.
Вот если Release стоял — тогда это повод очень хорошо задуматься.
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
Компилятор? Хм... Вроде как указал — 3.5. Если быть точным — 3.5.30729.1)
Запускал конечно в релизе, через студию, в дебаге чудес не жду).
Оптимизация в релизе естественно включена.
AS>Здравствуйте, bitferens, Вы писали:
B>>На моей машине (C2D 2.5GHz/Vista/.NET 3.5 SP1) выигрыш при использовании поля получается чуть ли не в 5 раз.
B>>Вопрос: как понимать результаты подобной оптимизации?
AS>Сразу же будет вопрос: какой компилятор, какой режим компиляции (дебаг/релиз), как запускал, какие настройки компиляции.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, _FRED_, Вы писали:
_FR>>Запусти не через студию. Перед этим прогони сборку через NGen.
_FR>У меня вот такие результаты этих вот тестов:
Здравствуйте, 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.
Здравствуйте, 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, а обозначения оставил...
Видно, что присваивание свойства выливается в косвенный вызов. Хотя, судя по времени выполнения (не из студии), его быть не должно.
Есть ли какая-то возможность посмотреть, что реально генерирует JIT-компилятор?
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, bitferens, Вы писали:
B>>Запускал конечно в релизе, через студию, в дебаге чудес не жду). B>>Оптимизация в релизе естественно включена.
_FR>Запусти не через студию. Перед этим прогони сборку через NGen.
Здравствуйте, 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 Name
Microsoft Windows XP Professional
Version
5.1.2600 Service Pack 3 Build 2600
Processor
Intel Core2Duo CPU E8400 @ 3.00GHz
Processor
x86 Family 6 Model 23 Stepping 6 GenuineIntel ~3003 Mhz
Hardware Abstraction Layer
Version = "5.1.2600.5512 (xpsp.080413-2111)"
Total Physical Memory
4,096.00 MB
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _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.
Здравствуйте, 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>Черт знает что.