none
Что делает компилятор 20 секунд, перед тем как зайти в метод. RRS feed

  • Вопрос

  • Всем доброго времени суток!

    Столкнулся с такой проблемой, есть класс, который создается с помощью CodeDom (порядка 90 000 строк). Создаю его экземпляр. При попытке вызвать метод инициализации приложение виснет на 20 секунд и после этого выполняется метод. При чем такое поведение как в релизе, так и в дебаге. При переходе в тело метода через студию такая же ситуация.

    Вопрос, что происходит с CLR? Где это можно посмотреть и как? Профайлер показывает, что метод выполняется 15 миллисекунд, все остальное время непонятно на что тратится.

    Далее код:

    Базовый класс для класса значений:

    public abstract class ValueBase<TValue>
    {
    }

    Интерфейс для класса значений:

    public interface IParamValue
    {
        void InitValue(object value);
    }

    Класс значений:

    public class ParamValueDouble : ValueBase<double>, IParamValue
    {
        public void InitValue(object value)
        {
        }
    }

    Базовый класс для генерируемого класса:

    public class Base<TValueType,TValue> { public delegate TValueType GetValue();

    protected Dictionary<string, Dictionary<DateTime, GetValue>> calculateMethods;

    }


    Сам генерируемый класс (у меня 11000 методов вида P1 - P11000):

    public class calculate : Base<ParamValueDouble, double> {

    public ParamValueDouble P1()

    {

    return 0;

    }

    //и т.д.

    public void InitMethods() { calculateMethods = new Dictionary<string, Dictionary<DateTime, GetValue>>();

    methods = new Dictionary<DateTime, GetValue>();

    methods.Add(new DateTime(...), P1);

    calculateMethods.Add("Code1", methods);

    //и т.д. } }

    При вызове метода InitMethods, приложение виснет на 20 секунд, есть идеи? Пока решил переделать.

    14 марта 2013 г. 17:24

Ответы

  • Всем доброго времени суток!

    Форумы ничего полезного не дали, все попробовал, но результат был нулевой.

    В общем удалось победить данную проблему следующим образом.

    1) Тестовый стенд x64 (проект AnyCPU), затраты времени 5 секунд JIT;
    2) Тестовый стенд x86 (проект AnyCPU), затраты времени 5 секунд JIT;
    3) Тестовый стенд x64 (проект x86), затраты времени 10 миллисекунд JIT;
    4) Тестовый стенд x86 (проект x86), затраты времени 10 миллисекунд JIT;
    5) Тестовый стенд x64 (проект x64), затраты времени 10 миллисекунд JIT;

    Т.е. работа JIT напрямую зависела от выбранной платформы для компиляции проекта.

    Проблему решил, но вопросы остались.
    Всем спасибо за ответы.
    • Помечено в качестве ответа GrishaCo 18 марта 2013 г. 12:13
    18 марта 2013 г. 12:12
  • Могу ещё порекомендовать задать этот вопрос на форуме rsdn.ru, в разделе .net. Дело в том, что там среди участников есть несколько сотрудников Microsoft, работающих непосредственно над компилятором C# (и Roslyn). Полагаю, они смогут дать ответ.

    • Помечено в качестве ответа GrishaCo 16 марта 2013 г. 17:14
    16 марта 2013 г. 11:31

Все ответы

  • Покажите собранную модель исходного кода, чтобы можно было сразу скомпилировать и посмотреть.
    14 марта 2013 г. 18:54
    Модератор
  • При самом первом вызове метода сперва происходит его JIT-компиляция, а затем он выполняется. Если я правильно пониманю, при вызове InitMethods будут компилироваться все 11000 сгенерированных методов. Вероятно, именно на это уходит время.

    А если повторно вызвать этот метод, времени тратится столько же?

    14 марта 2013 г. 20:30
  • Доброго времени суток.

    К сожалению не могу вставить ссылку на проект. Моя учетка еще не проверена.

    Может есть возможность вставить по другому ссылку? И как долго учетка проверяется?

    • Изменено GrishaCo 15 марта 2013 г. 7:20
    15 марта 2013 г. 7:17
  • Доброго времени суток.

    Возможно и происходит компиляция 11000 методов, но где это посмотреть и как?

    Если вызывать повторно, то все нормально, выполнение метода занимает около 15 миллисекунд. 

    15 марта 2013 г. 7:19
  • > но где это посмотреть и как?

    К сожалению, этого я не знаю.

    Могу лишь дать советы общего плана. Если эти методы генерируются один раз, и далее не изменяются, то можно попробовать применить утилиту NGEN - она создаст предварительно-скомпилированную сборку. А дальше использовать эту сборку, и не будет потерь времени на JIT-компиляцию. Однако, не всегда можно применить ngen.

    Ещё один совет (возможно, бесполезный): сделать тот большой класс sealed - запечатанным (естественно, если у него не будет потомков). В ряде случаев (не всегда) это позволит компилятору создавать более оптимальный код (впрочем, если не ошибаюсь, это относится только к виртуальным методам). Однако, полагаю, это не поможет ускорить jit-компиляцию.

    15 марта 2013 г. 10:09
  • Утилиту NGEN использовать не могу, т.к. данный класс генерируется по событию, т.е. пользователь поменял формулу, необходимо собрать новый класс. Кстати sealed не помог.
    15 марта 2013 г. 10:39
  • "К сожалению не могу вставить ссылку на проект." - я не про весь проект, а только код который собирается с CodeDOM.
    15 марта 2013 г. 11:34
    Модератор
  • Класс, который создается с помощью CodeDom содержит порядка 90 000 строк. Вы действительно хотите, что-бы я вставил этот кусок кода сюда?
    15 марта 2013 г. 13:58
  • Могу ещё порекомендовать задать этот вопрос на форуме rsdn.ru, в разделе .net. Дело в том, что там среди участников есть несколько сотрудников Microsoft, работающих непосредственно над компилятором C# (и Roslyn). Полагаю, они смогут дать ответ.

    • Помечено в качестве ответа GrishaCo 16 марта 2013 г. 17:14
    16 марта 2013 г. 11:31
  • Всем доброго времени суток!

    Форумы ничего полезного не дали, все попробовал, но результат был нулевой.

    В общем удалось победить данную проблему следующим образом.

    1) Тестовый стенд x64 (проект AnyCPU), затраты времени 5 секунд JIT;
    2) Тестовый стенд x86 (проект AnyCPU), затраты времени 5 секунд JIT;
    3) Тестовый стенд x64 (проект x86), затраты времени 10 миллисекунд JIT;
    4) Тестовый стенд x86 (проект x86), затраты времени 10 миллисекунд JIT;
    5) Тестовый стенд x64 (проект x64), затраты времени 10 миллисекунд JIT;

    Т.е. работа JIT напрямую зависела от выбранной платформы для компиляции проекта.

    Проблему решил, но вопросы остались.
    Всем спасибо за ответы.
    • Помечено в качестве ответа GrishaCo 18 марта 2013 г. 12:13
    18 марта 2013 г. 12:12