C # функция нормальное возвращаемое значение VS out или ref аргумент - PullRequest
6 голосов
/ 16 мая 2010

У меня есть метод в C #, который должен возвращать очень большой массив (или любую другую большую структуру данных в этом отношении).

Есть ли прирост производительности при использовании параметра ref или out вместо стандартного возвращаемого значения?

т.е. есть ли какая-либо производительность или другой выигрыш при использовании

void function(sometype input, ref largearray)

над

largearray function(sometype input)

Ответы [ 4 ]

5 голосов
/ 16 мая 2010

Объем стекового пространства, используемого 32-разрядным процессором x86 для передачи аргументов различных типов:

  • байт: 4 байта
  • bool: 4 байта
  • перечисление: 4 байта
  • char: 4 байта
  • short: 4 байта
  • int: 4 байта
  • длинный: 8 байтов
  • float: 4 байта
  • двойной: 8 байтов
  • десятичное число: 16 байтов
  • struct: размер структуры во время выполнения

  • строка: 4 байта
  • массив: 4 байта
  • объект: 4 байта
  • интерфейс: 4 байта
  • указатель: 4 байта
  • экземпляр класса: 4 байта

Те, что ниже линии, являются ссылочными типами, их размер удваивается на 64-битном процессоре.

Для статического вызова метода первые 2 аргумента длиной до 4 байтов будут передаваться через регистры ЦП, а не через стек. Для вызова метода экземпляра только один аргумент будет передан через регистры. Остальные передаются в стек. 64-разрядный процессор поддерживает передачу 4 аргументов через регистры.

Как видно из списка, единственный раз, когда вы должны рассмотреть возможность передачи аргумента с помощью ref, - это структуры. Обычное руководство для этого - делать это, когда структура больше 16 байтов. Не всегда легко угадать размер структуры во время выполнения, обычно до 4 полей будут точными. Меньше, если эти поля двойные, длинные или десятичные. Это руководство обычно рекомендует преобразовать вашу структуру в класс именно по этой причине.

Также обратите внимание, что не экономит , передавая аргумент в виде байта или короткого замыкания преднамеренно, int - это тип, который устраивает 32-разрядный процессор. То же самое для доступных в настоящее время 64-разрядных процессоров.


Возвращаемое значение метода, реальная тема вашего вопроса почти всегда возвращается в регистр процессора. Большинство типов удобно помещаются в регистры eax или edx: eax, регистр FPU для значений с плавающей запятой. Единственным исключением являются большие структуры и десятичные числа, они слишком велики, чтобы соответствовать регистру. Они вызываются путем резервирования пространства в стеке для возвращаемого значения и передачи 4-байтового указателя на это пространство в качестве аргумента метода.

1 голос
/ 16 мая 2010

Нет, просто верните массив

1 голос
/ 16 мая 2010

Там не будет никакой разницы между

void function(sometype input, out largearray output ) 

над

largearray function(sometype input)

Однако, если вы делаете

largearray function( sometype input, ref largearray output )

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

1 голос
/ 16 мая 2010

Параметр out возвращает ссылку на экземпляр типа, который не нужно было инициализировать перед отправкой в ​​метод.

Параметр ref возвращает ссылку на экземпляр типа, который должен быть инициализирован перед отправкой в ​​метод.

Речь идет о семантике вызовов, а НЕ о производительности.

...