0

I am starting to work on a polygon library, whose side are bezier curves. The basic don't quite work yet so I can't really write stress / performance test program yet. nor show much code.

At any rate I have classes like that

public class BezierFragment
{
    Point2D[] controlPoints; // length: 2, 3 or 4
}
public struct Point2D { public double X, Y; }

But I am wondering whether I should instead use struct (for less heap allocation and more stack copies)

public struct BezierFragment
{
    byte order; // 2, 3, or 4
    Point2D p0, p1, p2, p3;
}
public struct Point2D { public double X, Y; }

The later is much easier on the memory management, but might require more copy (of 65 bytes) struct. I wonder which one would be best. How would I figure out the best option?

The (possible) memory management issues of the first choice might only be apparent when lots of Point2D[] array are saved in generation 2 memory pool and then destroyed...

Any tip?

  • 2
    **[Choosing Between Class and Struct](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct)** – Ňɏssa Pøngjǣrdenlarp Feb 14 '18 at 01:32
  • Excellent link, thanks! :) – Lloyd Dupont Feb 14 '18 at 01:42
  • 1
    Your class and sruct examples here are different things anyway so you can't really compare them. – DavidG Feb 14 '18 at 01:51
  • DavidG, I am not sure what confuse you....BezierFragment is always a 2-3-or-4 points thing, and I just highlighted a class and struct version for what is essentially the same information. I dunno what you saw... But you didn't see the right thing, obviously... – Lloyd Dupont Feb 14 '18 at 02:50

1 Answers1

3

Given

class Foo : Attribute
{
   public int I { get; set; }
}

struct Foo2 
{
   public int I { get; set; }
}

And

private static void Method1(Foo foo)
{
   foo.I = 1;
}
private static void Method2(Foo2 foo2)
{
   foo2.I = 1;
}

Usage

var foo = new Foo();
//IL_0001: newobj       instance void ConsoleApp3.Foo::.ctor()
//IL_0006: stloc.0      // foo

var foo2 = new Foo2();
//IL_0007: ldloca.s     foo2
//IL_0009: initobj      ConsoleApp3.Foo2

Method1(foo);
//IL_0000: nop          
//IL_0001: ldarg.0      // foo
//IL_0002: ldc.i4.1     
//IL_0003: callvirt     instance void ConsoleApp3.Foo::set_I(int32)
//IL_0008: nop          
//IL_0009: ret   

Method2(foo2);
//IL_0000: nop          
//IL_0001: ldarga.s     foo2
//IL_0003: ldc.i4.1     
//IL_0004: call         instance void ConsoleApp3.Foo2::set_I(int32)
//IL_0009: nop          
//IL_000a: ret  

Not a lot going on there


However, if you want to know what goes on the heap there is a bit more to the story

Memory usage in .NET when creating a new class or struct

A single reference either takes 4 bytes on 32-bit processes or 8 bytes on 64-bit processes. A reference is a standard overhead on classes (as they are reference types). Structs do not incur references (well, ignoring any potential boxing) and are the size of their content usually. I cannot remember if classes have any more overhead, don't think so.

Does using “new” on a struct allocate it on the heap or stack?

Also as already pointed out, there are more considerations

Some more reading

Coding for performance: Struct vs Class


Even Further reading

Choosing Between Class and Struct

CONSIDER defining a struct instead of a class if instances of the type are small and commonly short-lived or are commonly embedded in other objects.

More so

X AVOID defining a struct unless the type has all of the following characteristics:

  • It logically represents a single value, similar to primitive types (int, double, etc.).

  • It has an instance size under 16 bytes.

  • It is immutable.

  • It will not have to be boxed frequently.

In all other cases, you should define your types as classes.

Since your interested in performance, look at this as well

Writing Faster Managed Code: Know What Things Cost

TheGeneral
  • 79,002
  • 9
  • 103
  • 141