views:

195

answers:

4

I've got a method in C# that needs to return a very large array (or any other large data structure for that matter).

Is there a performance gain in using a ref or out parameter instead of the standard return value?

I.E. is there any performance or other gain in using

void function(sometype input, ref largearray)

over

largearray function(sometype input)
+1  A: 

An out parameter returns a reference to an instance of type, which wasn't required to be initialised before sending into a method.

A ref parameter returns a reference to an instance of type, that must be initialised before sending in to a method.

This is about call semantics, NOT performance.

Mitch Wheat
+1  A: 

There isn't, just return the array

Ion Todirel
+1  A: 

There would be no difference between

void function(sometype input, out largearray output ) 

over

largearray function(sometype input)

However, if you do

largearray function( sometype input, ref largearray output )

and you require the caller to have pre-allocated the large array, that would of course be faster, but it would only matter if you call the method repeatedly and keep the large array allocated between calls.

danbystrom
A: 

The amount of stack space used on a 32-bit x86 processor to pass arguments of various types:

  • byte: 4 bytes
  • bool: 4 bytes
  • enum: 4 bytes
  • char: 4 bytes
  • short: 4 bytes
  • int: 4 bytes
  • long: 8 bytes
  • float: 4 bytes
  • double: 8 bytes
  • decimal: 16 bytes
  • struct: runtime size of the structure

  • string: 4 bytes
  • array: 4 bytes
  • object: 4 bytes
  • interface: 4 bytes
  • pointer: 4 bytes
  • class instance: 4 bytes

The ones below the line are reference types, their size will double on a 64-bit processor.

For a static method call, the first 2 arguments that are up to 4 bytes will be passed through CPU registers, not the stack. For an instance method call only one argument will be passed through registers. The rest are passed on the stack. A 64-bit processor supports passing 4 arguments through registers.

As is clear from the list, the only time you should ever consider passing an argument by ref is for structures. The normal guidance for this is to do so when the structure is larger than 16 bytes. It isn't always easy to guess the runtime size of a structure, up to 4 fields would usually be accurate. Less if those fields are double, long or decimal. This guidance then usually recommends turning your structure into a class, precisely for this reason.

Also note that there is no savings passing an argument as a byte or short intentionally, an int is the type that a 32-bit processor is happy with. Same for currently available 64-bit processors.


A method return value, the real topic of your question are almost always returned in a CPU register. Most types fit comfortably in the eax or edx:eax registers, an FPU register for floating point values. The only exceptions are large structures and decimal, they are too large to fit a register. They are called by reserving space on the stack for the return value and passing a 4 byte pointer to that space as an argument to the method.

Hans Passant
This is the answer I am looking for. I can't see how to flag this as an answer though - I am a newbie and I bit blind perhaps?
@misha: there's a check mark next to my post, outlined in black, white interior. Click it to mark the answer.
Hans Passant