Я нахожу ироничным то, что ответ Бена гласит, что «используйте науку: измерьте ее, чтобы узнать», и «вот мое убеждение в том, что действительно происходит»:ЛЮБАЯ производительность хит там.Общие методы JITted для каждого типа значения, этот процесс должен полностью устранить любое воображаемое снижение производительности.
Исходя из фактической разборки, показанной в обновленном вопросе, оригинальный постер утверждает, что используемый джиттер, по-видимому, выполняет эту оптимизацию по крайней мере некоторое время.Я не проанализировал это утверждение, чтобы убедиться, что оно правильное;Я бы хотел увидеть реальный скомпилированный код, IL и сгенерированную сборку, чтобы понять, что здесь происходит.
В своих исследованиях в этой области в прошлом я обнаружил множество ситуацийв котором верификатор и джиттер были недостаточно хитрыми, особенно в отношении устранения штрафов за бокс. Были ли они устранены, я не знаю.
Если некоторые из них были устранены, тогда я с удовольствием узнаю об этом.
Поэтому вы не можете сделать вывод prima facie , что джиттер выполняет или не выполняет эту оптимизациюустранения бокса.Я видел случаи, когда это не так;у нас есть непроверенное утверждение, что в некоторых случаях это действительно так.
Бен продолжает давать несколько полезных советов:
Но вы можете продемонстрировать, что на самом деле это ценас помощью данных о производительности (реальных измерений профилировщика) или, по крайней мере, разборки машинного кода, сгенерированного JIT.
Действительно, я настоятельно рекомендую вам это сделать и при наличии более одного дрожания.
Давайте начнем сначала и ответим на фактически заданные вопросы.Мы должны начать с упрощения и прояснения описанного случая:
abstract class B
{
public abstract T M<T>() where T : struct;
}
private class D<U> : B where U : struct
{
public override V M<V>()
{
U u = default(U);
return (V)u; // compile-time error
}
}
Оригинальный плакат гласит, что V всегда будет таким же, как U. Есть первая проблема.Зачем?Ничто не мешает пользователю вызвать M<bool>
в экземпляре D<double>
.Средство проверки типов совершенно правильно, отметив, что преобразование из U в V. может не произойти.
Как отмечает оригинальный автор, можно выполнить окончательный обход средства проверки типов, выполнив упаковку и распаковав код:
return (V)(object)u; // Runtime error, not compile-time error
Тогда возникает вопрос: «В случае, если это не дает сбой и ужасно умирает во время выполнения, устраняется ли штраф в боксе дрожанием?»
Джиттер джитит метод только один раз и разделяет код для аргументов ссылочного типа, но каждый раз повторно джитит его для различных параметров типа значения.Следовательно, существует возможность отменить штраф, когда конкретные аргументы, предоставленные для U и V, имеют одинаковый тип значения.
Я задавался этим вопросом один раз несколько лет назад и , поэтому я проверил .Я не проверял более свежие сборки джиттера, но в прошлый раз, когда я проверял, штраф за бокс был , а не .Джиттер выделяет память, копирует значение в кучу, а затем снова копирует его обратно.
Очевидно, согласно обновленному вопросу, это уже не так;протестированный джиттер теперь выполняет эту оптимизацию.Как я уже сказал, я не проверял это утверждение сам.
Джиттер разрешен для выполнения этой оптимизации, но в прошлый раз, когда я проверял, на практике это не так, поэтому мы знаем, что тамв дикой природе есть по крайней мере один джиттер, который не делает эту оптимизацию.
Более интересный пример - тот, где аргументы типа ограничены равными:
abstract class E<T>
{
public abstract U M<U>(T t) where U : T;
}
class F<V> : E<V> where V : struct
{
public override W M<W>(V v)
{
return v; // Error
}
}
Опять же, это недопустимо, , хотя компилятор C # может логически вывести, что W теперь должен быть идентичен V.
Вы можете снова ввести приведение, чтобы решить проблему,но анализатор типа верификатора IL требует, чтобы V было упаковано и распаковано как W.
И еще раз, джиттер мог сделать вывод, что бокс и распаковка запрещен, и устранить его, но в прошлый раз, когда я проверял, этого не произошло. Это может сейчас; попробуй и посмотри.
Я сообщил об этом в качестве возможной оптимизации команде джиттера; они сообщили мне, что у них много высших приоритетов, что является вполне разумным ответом. Это малопонятный и маловероятный сценарий, который я бы тоже не расставил по приоритетам.
Если на самом деле эта оптимизация уже выполнена, то я приятно удивлен.