powered by simpleCommunicator - 2.0.29     © 2024 Programmizd 02
Map
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Source Generators, варианты?
11 сообщений из 11, страница 1 из 1
Source Generators, варианты?
    #40088976
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Во многих языках есть клевые конструкции мета программирования, например в Rust/Nemerle(☦) макросы, в F# - провайдеры типов/выражения вычисления и т. д.
Не так давно Боги сниспослали нам Source Generators
Штука вроде крутая, хотелось бы понять, куда ее пристроить и как извлечь пользу. Предлагаю лучшим умам .NET`а в этом топике поразмышлять над этими вопросами.
Сам пока надумал вот что.
1. Можно получить некоторый аналог шаблонов в С++, когда в основном коде некоторая бутафорская конструкция не вызывающая ошибку компиляции, но дающая информацию для генерации кода, например сведения о типах. Возможно выиграем в быстродействии. В F# например изначально существуют как женерики в стиле .NET, так и разворачивание шаблона в код, в стиле С++.
2. Можно сделать наконец то нормальный IoC контейнер, который на основании например
Код: c#
1.
ninjectKernel.Bind<IRepository>().To<BookRepository>();


будет заменять такую мутоту с кешированием и всякими Reflection/ExpressonTree
Код: c#
1.
repo = ninjectKernel.Get<IRepository>();


на прямой вызов конструктора или что там в зависимости от скоупа
правда пока не придумал, как красиво это сделать...
...
Рейтинг: 0 / 0
Source Generators, варианты?
    #40089004
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если непонятно
ЕвгенийВ
куда ее пристроить и как извлечь пользу.
то стоит ли пока что заморачиваться? :))

ЕвгенийВ
разворачивание шаблона в код, в стиле С++.
Отладка шаблонов в С++ это ад.

ЕвгенийВ
будет заменять такую мутоту с кешированием и всякими Reflection/ExpressonTree
ExpressionTree как раз и развернется в прямой вызов конструктора.
...
Рейтинг: 0 / 0
Source Generators, варианты?
    #40089093
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
ExpressionTree как раз и развернется в прямой вызов конструктора.

Вообще вызов new constructor(... , в смысле выделения памяти, без действий описанных в конструкторе, довольно дешев и оптимизирован, но не бесплатен совсем.
В лучшем случае, если собираем его через ExpressionTree и конструктор без параметров - получим delegate.Invoke(), а это несколько лишних callvirt, проход по InvocationList и т. д.
...
Рейтинг: 0 / 0
Source Generators, варианты?
    #40089100
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
new - где то раз в 20 быстрее вызова делегата
...
Рейтинг: 0 / 0
Source Generators, варианты?
    #40089138
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВ
new - где то раз в 20 быстрее вызова делегата

Откуда именно такое число?
Мне недавно пришлось оптимизировать вызов статик-метода через рефлекшн (рефлекшн - поскольку тип, у которого надо было вызывать метод, internal и в другой сборке, которая не моя). Самым оптимальным оказался вариант конструирования делегата на основе MethodInfo, и скорость вызова такого делегата оказалась практически эквивалентной непосредственному вызову метода.
Если интересно - тест с бенчмарком и результаты здесь .
...
Рейтинг: 0 / 0
Source Generators, варианты?
    #40089187
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,
Львиную долю вносит выполнение Next() и ToString(), особенно последний, поэтому время выполнения не различается в разы.
Для замера именно времени вызова нужно максимально упростить Foo.Bar

Код: c#
1.
public static string Bar(int n) => "";


И передавать в него константу.
...
Рейтинг: 0 / 0
Source Generators, варианты?
    #40089215
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВ
Для замера именно времени вызова нужно максимально упростить Foo.Bar
И передавать в него константу.

В таком варианте бенчмарк-библиотека (стандартно, BenchmarkDotNet) не может измерить длительность прямого вызова метода, и выдает предупреждение

Код: plaintext
1.
2.
3.
// * Warnings *
ZeroMeasurement
  Program.DirectCall: Default -> The method duration is indistinguishable from the empty method duration

- видимо, в релизе (в debug-конфигурации запуск бенчмарков невозможен) происходит такая оптимизация, что фактически отсутствует сам вызов метода (IL не смотрел), и нужна какая-то минимальная нагрузка.
Если из бенчмарка выкинуть Random, и передавать в метод всегда константу (0), но оставить возврат n.ToString, то картина остается примерно прежней:

Код: plaintext
1.
2.
3.
4.
5.
6.
         Method |      Mean |     Error |    StdDev | Ratio |
--------------- |----------:|----------:|----------:|------:|
     DirectCall |  41.37 ns | 0.0629 ns | 0.0588 ns |  1.00 |
 ReflectionCall | 213.66 ns | 0.3773 ns | 0.3151 ns |  5.16 |
   DelegateCall |  42.94 ns | 0.0757 ns | 0.0671 ns |  1.04 |
 ExpressionCall |  54.52 ns | 0.1324 ns | 0.1173 ns |  1.32 |
...
Рейтинг: 0 / 0
Source Generators, варианты?
    #40089231
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
К черту бенчмарки, тут Stopwatch наше все :)
...
Рейтинг: 0 / 0
Source Generators, варианты?
    #40089297
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
    public class CtorCalls
    {
        private readonly Func<Foo> _fooCtor;

        public CtorCalls()
        {
            // () => new Foo()
            var body = Expression.New(typeof(Foo));
            var expr = Expression.Lambda<Func<Foo>>(body);
            _fooCtor = expr.Compile();
        }

        [Benchmark]
        public Foo[] DirectCall() => Enumerable.Repeat(0, 1024).Select(_ => new Foo()).ToArray();

        [Benchmark]
        public Foo[] DelegateCall() => Enumerable.Repeat(0, 1024).Select(_ => _fooCtor()).ToArray();
    }


Код: plaintext
1.
2.
3.
4.
|       Method |     Mean |    Error |   StdDev |
|------------- |---------:|---------:|---------:|
|   DirectCall | 13.69 us | 0.164 us | 0.153 us |
| DelegateCall | 14.37 us | 0.055 us | 0.049 us |

Разницы вообще нет
...
Рейтинг: 0 / 0
Source Generators, варианты?
    #40089301
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,
Что ты мерял?
...
Рейтинг: 0 / 0
Source Generators, варианты?
    #40089315
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВ
fkthat,
Что ты мерял?

Вызов конструктора. Напрямую и через делегат полученный компиляцией Expression. Код вызовов выше. Одиночный вызов слишком быстрый чтобы снять метрики, поэтому измеряется 1024 вызова.

Вызываемый класс:
Код: c#
1.
2.
3.
public class Foo
{
}



Но вообще, я думаю, если в приложении приходится постоянно создавать миллионы объектов, то стоит задуматься о дизайне в целом. Применять что-нибудь типа flyweight pattern .
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Source Generators, варианты?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]