передача по in
ссылке кажется логически эквивалентной передаче по значению.
Верный.
Есть ли какое-то преимущество в производительности?
Да.
Я считал, что на внутренней стороне вещей ref
параметр должен как минимум копировать физический адрес переменной, который должен быть того же размера, что и любая типичная ссылка на объект.
Не существует требования, чтобы ссылка на объект и ссылка на переменную были одинакового размера, и не требуется, чтобы любой из них был размером машинного слова, но да, на практике оба 32 бита на 32 битовые машины и 64-битные на 64-битных машинах.
Как вы думаете, какое отношение к этому имеет "физический адрес", мне неясно. В Windows мы используем виртуальные адреса , а не физические адреса в коде пользовательского режима. Мне любопытно знать, при каких возможных обстоятельствах вы можете представить, что физический адрес имеет значение в программе на C #.
Также не требуется, чтобы какая-либо ссылка была реализована как виртуальный адрес хранилища. Ссылки могут быть непрозрачными дескрипторами таблиц GC в соответствующей реализации спецификации CLI.
преимущество только в более крупных структурах?
Снижение стоимости передачи больших структур - мотивирующий сценарий для этой функции.
Обратите внимание, что нет никакой гарантии, что in
какая-либо программа действительно будет быстрее или медленнее. На все вопросы о производительности необходимо ответить эмпирическим исследованием . Очень мало оптимизаций, которые всегда приносят пользу ; это не всегда выигрышная оптимизация.
есть ли какая-то закулисная оптимизация компилятора, которая делает его привлекательным в других местах?
Компилятору и среде выполнения разрешается производить любую оптимизацию по своему усмотрению, если это не нарушает правил спецификации C #. Насколько мне известно, такой оптимизации для in
параметров еще нет , но это не исключает такой оптимизации в будущем.
почему бы мне не сделать каждый параметр входным?
Что ж, предположим, вы создали int
параметр вместо in int
параметра. Какие накладные расходы?
- для сайта вызова теперь требуется переменная, а не значение
- переменная не может быть зарегистрирована. Тщательно настроенная схема распределения регистров джиттера только что была добавлена в нее.
- код на сайте вызова больше, потому что он должен принимать ссылку на переменную и помещать ее в стек, тогда как раньше он мог просто поместить значение в стек вызовов
- Более крупный код означает, что некоторые инструкции короткого перехода теперь могли стать инструкциями длинного перехода, поэтому, опять же, код теперь больше. Это накладывает отпечаток на самые разные вещи. Кеши заполняются быстрее, дрожание требует больше работы, дрожание может не выполнять определенные оптимизации для больших размеров кода и так далее.
- на вызываемом сайте мы превратили доступ к значению в стеке (или регистре) в косвенное обращение к указателю. Теперь этот указатель, скорее всего, находится в кеше, но все же мы превратили доступ с одной инструкцией к значению в доступ с двумя инструкциями.
- И так далее.
Предположим, это a, double
и вы измените его на in double
. Опять же, теперь переменная не может быть зарегистрирована в высокопроизводительном регистре с плавающей запятой. Это не только влияет на производительность , но и может изменить поведение программы! C # разрешено выполнять арифметические операции с плавающей запятой с точностью выше 64-битной и обычно делает это только в том случае, если числа с плавающей запятой можно зарегистрировать.
Это не бесплатная оптимизация. Вы должны сравнить его производительность с альтернативами. Лучше всего просто вообще не создавать большие структуры, как предлагают рекомендации по дизайну.
ref
используется для передачи структур по ссылке вместо их копирования.in
означает, что структуру нельзя изменять.