#c_sharp #оптимизация #clr
Смотрю курсы по C# proffesional от ITVDN. Там пример, первый раз обращаются к полю
dynamic, которое раннее приравнено к ссылке на объект, и показывают, что первое обращение
к такому полю занимает 2 миллиона тиков. Я повторяю это на своем компьютере, но у меня
всего 2 тысячи тиков. Примерно в 10 раз больше, чем следующие обращения к dynamic.
Соль то в том, что dynamic запоминает объект, но в первый раз он ничего о нем не знает
и поэтому занимает больше времени. Но 2 тысячи и 2 миллиона для одинаковых функций
- очень большая разница. Может курс устарел и разработчики C# оптимизировали dynamic?
Код:
MyClass c = new MyClass();
dynamic d = c;
long start, end;
while (true)
{
QueryPerformanceCounter(out start);
d.m();
QueryPerformanceCounter(out end);
Console.WriteLine((end - start) + '\n');
}
Ответы
Ответ 1
На вопрос о разнице в количестве тиков отвечать не буду, потому как неизвестны ни способ измерения, ни конфигурации вашего и автора курса компьютеров, ни версии .NET. Вместо этого отвечу, почему первый вызов метода работает медленнее. Авось кому пригодится. Дополнения к посту приветствуются. Для каждого выражения (операции), использующего объект типа dynamic, компилятор генерирует специальный объект под названием dynamic call site, который представляет это выражение (операцию). После компиляции приведенного в вопросе кода получается примерно следующее (код с измерением опустил): static DynamicCallSite dCallSite; ... MyClass c = new MyClass(); dynamic d = c; while (true) { if (dCallSite == null) { dCallSite = new DynamicCallSite(); } dCallSite.DoInvocation("m", d); } При этом объект dynamic call site генерируется только один раз для каждого выражения. Это первая монетка в копилку "почему первый вызов работает медленнее". Дальше DLR проверяет типа объекта d, обнаруживает, что это C# объект, и вызывает С# компилятор, который, используя метаданные, генерирует expression tree для данного выражения. Expression tree возвращается обратно DLR, компилируется, получившийся делегат вызывается и кэшируется. Т.е. если DLR в дальнейшем встретит такое же выражения для объекта такого же типа, будет вызван закэшированный делегат. Это вторая монетка в копилку "почему первый вызов работает медленнее". Во время второго вызова у нас уже есть dynamic call site, так что DLR просто проверяет тип объекта, достает из кэша скомпилированный делегат и выполняет его.
Комментариев нет:
Отправить комментарий