Открыть список
Как стать автором
Обновить
29
Карма
0
Рейтинг

Пользователь

typeof(T) vs. TypeOf⟨T⟩

Что касается typeof, то в своих вольных проектах я везде заменил его на TypeOf, потому что для меня это самое оптимальное и универсальное решение для улучшения производительности.

Однозначно, при решении более общей задачи кэширования на основе дженерик ключа я буду рассматривать подобный подход в качестве одного из потенциальных решений.

Теперь осталось выяснить, не было ли лучшего способа решить вашу проблему.
К сожалению, способа получения информацию о типе минуя typeof или GetType я не знаю, но знаю, как её закэшировать для наиболее быстрого доступа в дальнейшем.

Мы же уже выяснили, что вы не делали анализа своих находок?
По моим личным критерия анализа, решения мне подходят. Вы свои критерии знаете куда лучше, поэтому применимость находок для себя сможете определить сами.

typeof(T) vs. TypeOf⟨T⟩

Как вам объяснить… Где я написал, что так нужно делать везде и всегда? Если вас устраивает вариант со словарём, то, пожалуйста, пользуйтесь!

В своей практике я дошёл до того момента, когда мне потребоволась кэшировать информацию о типах, чтобы достичь лушей производительности, и TypeOf с RipeType мне в этом помогли.

Дальше я просто поделился опытом с другими людьми, потому что до этих решений дошёл далеко не сразу, пришлось проводить различные замеры, эксперементировать с реализациями, разбираться с деталями. И своей статьёй, возможно, кому-то сохраню немало времени в дальнейшем.

У меня нет цели доказывать кому-то что-то или навязывать. Нравится решение — бери и используй, не нравится — пробуй другое.

typeof(T) vs. TypeOf⟨T⟩

Так в чём проблема сделать
EqualityComparerProvider.GetDefault<T>()

со словарём внутри, который предоставляет инстенсы EqualityComparer⟨T⟩? Почему выбрано иное решение?

typeof(T) vs. TypeOf⟨T⟩

Как я написал выше, оно хорошее в определённых дженерик случаях, где требуется высокая производительность.

typeof(T) vs. TypeOf⟨T⟩

Если бы совсем не в кэшировании и производительности, то можно было бы просто взять и на основе словаря, как у вас, сделать
EqualityComparer.GetDefault<T>()
.

typeof(T) vs. TypeOf⟨T⟩

Я вот вообще-то думал, что мы задачу про мемоизацию функции решаем.

Так и я же говорю, что в определённых дженерик случаях она прекрасно решается с высокой производительностью стататическим дженерик классом с рид-онли полем.

typeof(T) vs. TypeOf⟨T⟩

Можете сделать RipeType дженериком (хотя это избыточно для конкретной задачи), а TypeOf⟨T⟩ переименовать в RipeType⟨T⟩ — получится та же картина, что и с EqualityComparer⟨T⟩.

typeof(T) vs. TypeOf⟨T⟩

В этой дискуссии, я писал про более общий паттерн кэширования при помощи статического дженерик класса, где частными случаями являются TypeOf⟨T⟩ и EqualityComparer⟨T⟩. Насколько понимаю, вы имели ввиду под «ужасным» кодом именно этот общий случай, который я схематически обозначил, и свою критику вы не детализировали.

Мне очень жаль, что вы не видете аналогии и не можете проследить общий паттерн.

typeof(T) vs. TypeOf⟨T⟩

Рефлексия — частный случай более общего сценария с оптимиацией.

typeof(T) vs. TypeOf⟨T⟩

Так а что ужасного в TypeOf⟨T⟩.GetSomething()?

Не нравится TypeOf⟨T⟩.GetSomething(), используйте эквивалентную форму TypeOf⟨T⟩.Ripe.GetSomething(), что аналогично EqualityComparer⟨T⟩.Default.Equals(a, b)

typeof(T) vs. TypeOf⟨T⟩

Самое дешёвое и универсальное решение (если только у вас не микроконтроллер с минимумом памяти) в случае использования множественных рефлексивных вызовов на основе typeof в различных частях приложения — это замена этой конструкции на статическую версию TypeOf (может быть, лишь за редким исключением на определённых CLR при получении полного типа).

И насчёт «ужасного кода» вот яркий пример
EqualityComparer<T>.Default.Equals(a, b);

typeof(T) vs. TypeOf⟨T⟩

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

И заодно подумайте, почему
EqualityComparer<T>.Default.Equals(a, b);

реализован таким «ужасным» паттерном, а не хотя бы
EqualityComparer.GetDefault<T>().Equals(a, b);

typeof(T) vs. TypeOf⟨T⟩

Вот только замеров не видно и сравнения со статической версией.

typeof(T) vs. TypeOf⟨T⟩

private static readonly bool _value = ValueGetter();

static void AnyMethod<T>()
{
    ... = _value;
}

Возможно, я двусмысленно уточнил, но _value должно быть не общим значеним для любых T, а для каждого T конкретным. Под «достаточно одного T» имелось в виду, что у метода один дженерик параметр, а различных значений T пусть будет от 10 до 100.

Количество обращений более 100. Стоимость значения, как у typeof(T).Name/Assembly/IsValueType.

typeof(T) vs. TypeOf⟨T⟩

Чтобы уж точно не было разночтений по стоимости создания, можете просто взять за эталон работу с типами из публикации typeof(T).Name/Assembly/IsValueType.

Нужно сделать быстрее в два раза при множественных вызовах.

typeof(T) vs. TypeOf⟨T⟩

Зачем? Это единственно верная формулировка задачи?
В статье и примерах кода, которые вы так дерзко критикуете, решается по сути именно такая задача — закэшировать данные, зависящие от дженерик параметра, для последующего максимально быстрого доступа. Вы утверждаете, что код ужасен, тогда предложите правильное решение…

Критерии:
— минимальное время выполнения при многократных вызовах
— серьёзных ограничений по памяти нет, потребление в переделах разумного
— чтение многопоточное
— достаточно одного T
— кэшируемое значение любое (для простоты bool, string, object)
— стоимость создания определяется так: если кэшированный доступ даёт выигрыш по производительности в 2 и более раза в сравнении с созданием, то задача решена
— желательно ещё, чтобы это было справедливо для любой CLR (.NET Framework, .NET Core, Mono).

typeof(T) vs. TypeOf⟨T⟩

… а это удобно? Никогда бы не подумал. И код, который вы приводите, традиционно плох. Даже нет, не плох — ужасен.
Да? Тогда задачка для вас: закэшируйте значение в статическом дженерик методе AnyPerformanceCriticalMethod⟨T⟩(), зависящее от параметра T, это же просто, верно? Мне очень интересно увидеть ваше более оптимальное по производительности решение, потому что лучшего я не знаю, а хуже да, могу предложить.

В таком случае заодно можно считать, что этим статьям не место на хабре, потому что мне хочется думать, что аудитория здесь не состоит из «таких же тугодумов».
Вам, может, и хочется так думать, но своих читателей на Хабре публикации находят.

typeof(T) vs. TypeOf⟨T⟩

Для проведения дополнительных тестов открыты все исходные коды. Можно модифицировать их по своему усмотрению и проверять различные интересующие сценарии.

Так что любой товарищ, участвующий в споре или наблюдающий за ним со стороны, может их провести.

typeof(T) vs. TypeOf⟨T⟩

Здорово, а я вот лет 7 пользовался дженериками и только на седьмом году чётко понял, что кэшировать переменную в дженерик-методе удобно через статический дженерик класс.

class Cache<T>
{
    public object Instance { get; }
}

static void AnyMethod<T>()
{
    var anyInstance = Cache<T>.Value ?? 
    Cache<T>.Value = ReadOrCreate<T>();
}

Поэтому можете считать, что свои посредственные статьи пишу для таких же тугодумов, как и я сам, если вам так проще.

Возможно, вы уже ушли далеко вперёд в своём профессиональном развитии и для вас все эти замеры выглядят бессмысленно, но со скромных высот моих познаний смысл в них всё же есть.

typeof(T) vs. TypeOf⟨T⟩

Извините, конечно, но в дженерик случае через статических класс — это не настолько очевидно, как в обычном. Вы сами-то применяли осознанно такое решение раньше? А если применяли, то на каком году программирования дошли?

… и о чем же?
Оставляю на ваш суд.

Про чайник теперь услышал.

Информация

В рейтинге
5,747-й
Зарегистрирован
Активность