Search Unity

StructLayout does not work for "class" in Unity 4.6.9

Discussion in 'Scripting' started by pippocao, Apr 5, 2016.

  1. pippocao

    pippocao

    Joined:
    Apr 10, 2014
    Posts:
    16
    Code (CSharp):
    1.     [StructLayout(LayoutKind.Sequential, Pack = 4)]
    2.     public class A1
    3.     {
    4.         public int aaa;
    5.         public byte c1;
    6.         public byte c2;
    7.         public byte c3;
    8.         public byte c4;
    9.         public byte c5;
    10.         public byte c6;
    11.     }
    12.  
    13.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
    14.     public class A2
    15.     {
    16.         public int aaa;
    17.         public byte c1;
    18.         public byte c2;
    19.         public byte c3;
    20.         public byte c4;
    21.         public byte c5;
    22.         public byte c6;
    23.     }
    I declared 2 classes A1 and A2 with different StructLayout. And print the size of it using:

    Code (CSharp):
    1. Debug.Log(Marshal.SizeOf(typeof(A1)));
    2.  Debug.Log(Marshal.SizeOf(typeof(A2)));
    I can see size of A1 is 12 and size of A2 is 10.

    after that, I allocated a big array with A1, using code:
    Code (CSharp):
    1. A1[] aa = new A1[10000000];
    2. for(int i = 0; i < aa.Length; ++i)
    3. {
    4.      aa[i] = new A1();
    5. }
    And watch the mono size in profiler window which takes 278.9M memory.

    and then, I modify A1 to A2, and run the test again, but the mono size is still 278.9M, no difference from A1.


    Why?


    finally I change A1 and A2 to "struct", and run test again, I can see mono size is 124M and 100M in these two cases.

    does StructLayout only works for "struct"?
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    Classes are reference types, structs are value types.

    An array of reference types in memory is just an array of the pointers to the location of the referenced object.

    An array of value types in memory is a contiguous block of memory that the values are stored in, one after the other.
     
    Kiwasi likes this.
  3. pippocao

    pippocao

    Joined:
    Apr 10, 2014
    Posts:
    16
    Code (CSharp):
    1. A1[] aa = new A1[10000000];
    2. for(int i = 0; i < aa.Length; ++i)
    3. {
    4.      aa[i] = new A1();
    5. }
    I've called "new" operator to allocate the memory of 10000000 objects in mono heap, not just the array of pointer.
     
  4. DanHedges

    DanHedges

    Joined:
    Jan 21, 2016
    Posts:
    77
    The difference is because it is a value type as lordofduct said. When creating a struct the memory is allocated BEFORE the new is called. New will create a temporary store, initilaise the values in the struct then copy them to the preallocated memory. This memory will be contiguous as previously mentioned. There was a good explanation on StackOverflow about this...

    The whole answer is here http://stackoverflow.com/questions/...truct-without-the-new-keyword/7769694#7769694

    The StructLayout attribute can be applied to both a Struct and a Class, but they are stored differently, hence the effect you are seeing.
     
  5. pippocao

    pippocao

    Joined:
    Apr 10, 2014
    Posts:
    16
    Thanks for your explain.
    do you mean StructLayout perform different between "long term storage" and "short term storage"? but seems that it did totally nothing in "long term storage", different memory layout use the same memory size.
     
  6. DanHedges

    DanHedges

    Joined:
    Jan 21, 2016
    Posts:
    77
    From the C# language specification...

    Basically a struct will be allocated with all its members contiguous and can be affected in memory by the struct layout attribute. A class will be allocated by the memory manager depending on the availability of memory on the heap and what will be most performant for the CLR, it wont try and make it contiguous or as it has no need to, it has references to its members.

    The StructLayout attribute applied to a class will be used when marshalling the values to unmanaged code (when calling a c++ or COM library for instance) that expects a particular layout in order to be able to use the structure correctly.
     
  7. pippocao

    pippocao

    Joined:
    Apr 10, 2014
    Posts:
    16
    Thanks! you solved my mystery