Время выполнения инициализации объекта в узком цикле - PullRequest
1 голос
/ 21 февраля 2012

У меня есть три метода в c #, которые запускают один и тот же код, но с небольшой разницей, мой первый блок кода -

Stopwatch s = new Stopwatch();
object o = new object();
s.Start();
for (int i = 0; i < 100000000; i++)
{
    o.ToString();
    o.GetType();
    o.GetHashCode();
}
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds); //3100ms

и это стоит 3100 мс для запуска. Затем, если я сделаю инициализацию объекта внутри for, это увеличится до 7200ms, мой блок кода будет выглядеть так:

Stopwatch s = new Stopwatch();
s.Start();
for (int i = 0; i < 100000000; i++)
{
    object o = new object();
    o.ToString();
    o.GetType();
    o.GetHashCode();
}
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);//7200ms

Однако, если я инициализирую свой объект, но не использую какой-либо метод внутри, это будет стоить 652 мс. И мой код такой же,

Stopwatch s = new Stopwatch();
s.Start();
for (int i = 0; i < 100000000; i++)
{
    object o = new object();
}
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);//625ms

Интересно, 3100мс + 625мс несопоставимо с 7200мс. Что вызывает такую ​​большую разницу между первыми двумя?

Ответы [ 2 ]

3 голосов
/ 21 февраля 2012

Во втором блоке вы вызываете GetHashCode() для множества новых объектов.Из того, что я помню, когда в первый раз для объекта вызывается не переопределенный метод GetHashCode(), для него выделяется синхронизирующий блок.Это относительно дорого, хотя последующие вызовы GetHashCode для того же объекта (согласно вашему первому коду) дешевы.

Так что нужно помнить три вещи:

  • Стоимость выделения объекта (и любого GC)
  • Стоимость первого вызова метода
  • Стоимость последующих вызовов методов

Это, конечно, обобщение - многие методы занимают одинаковое количество времени, сколько бы раз вы их ни вызывали, а другие могут быть медленными (скажем) для первых 10 вызовов и быстрыми после этого.Я считаю, что в случае GetHashCode() это территория "первый звонок дорогой".Попробуйте это с типом, который переопределяет GetHashCode() некоторым простым способом, и я подозреваю, что вы найдете время, потраченное на падение.

Кроме того, возможно, что GetType() потребуется некоторое время для создания Type для object в самый первый раз это называется - я не уверен.По сути, вы здесь измеряете кучу разных вещей, что всегда приводит к сложному анализу.

0 голосов
/ 21 февраля 2012

Я бы декомпилировал методы с помощью Refactor или чего-то в этом роде и увидел бы сгенерированный IL. Вероятно, ответ есть.

...