Why is 16 byte the recommended size for struct in C#?

后端 未结 7 474
心在旅途
心在旅途 2020-11-29 07:20

I read the Cwalina book (recommendations on development and design of .NET applications).

He says that a good designed struct has to be less than 16 bytes in size (f

相关标签:
7条回答
  • 2020-11-29 07:37

    I think another key point is that if you have a list with a million structs, that is still only one memory allocation on the heap, while a list with a million classes in it is going to have about a million separate heap objects. The garbage collection load is something quite different in both cases. From this point of view, the struct may come out ahead.

    0 讨论(0)
  • 2020-11-29 07:40

    Only you know how your structs are being used in your program. But if nothing else, you can always test it for yourself. For instance, if it's frequently passed to other functions, the following may illuminate you:

    class MainClass
    {
        static void Main()
        {
            Struct64 s1 = new Struct64();
            Class64 c1 = new Class64();
            DoStuff(s1);
            DoStuff(c1);
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < 10000; i++)
            {
                s1 = DoStuff(s1);
            }
            sw.Stop();
            Console.WriteLine("Struct {0}", sw.ElapsedTicks);
            sw.Reset();
    
            sw.Start();
            for (int i = 0; i < 10000; i++)
            {
                c1 = DoStuff(c1);
            }
            sw.Stop();
            Console.WriteLine("Class {0}", sw.ElapsedTicks);
            sw.Reset();
    
            Console.ReadLine();
        }
    }
    

    with:

    public class Class64
    {
        public long l1;
        public long l2;
        public long l3;
        public long l4;
        public long l5;
        public long l6;
        public long l7;
        public long l8;
    }
    public struct Struct64
    {
        public long l1;
        public long l2;
        public long l3;
        public long l4;
        public long l5;
        public long l6;
        public long l7;
        public long l8;
    }
    

    Try this sort of thing with representative structs/classes, and see what results you get. (On my machine, above test, the class seems ~3 times faster)

    0 讨论(0)
  • 2020-11-29 07:43

    You're misquoting the book (at least the 2nd edition). Jeffrey Richter states value types can be more than 16 bytes if:

    You don't intend to pass them to other methods or copy them to and from a collection class.

    Additionally Eric Gunnerson adds (regarding the 16 byte limit)

    Use this guideline as a trigger to do more investigation.

    It is simply not true that a struct "has to be less than 16 bytes in size". It all depends on usage.

    If you are creating the struct and also consuming it and are worried about performance then use a profiler comparing a struct vs class to see which works best for you.

    0 讨论(0)
  • 2020-11-29 07:45

    The JIT compiler produces special-case code to copy structures which are smaller than a certain thresholds, and a somewhat-slower general-purpose construct for larger ones. I would conjecture that when that advice was written, the threshold was 16 bytes, but in today's 32-bit framework it seems to be 24 bytes; it may be larger for 64-bit code.

    That having been said, the cost of creating any size class object is substantially greater than the cost of copying a struct which holds the same data. If code creates a class object with 32 bytes worth of fields and then passes or otherwise copies a reference to that object 1,000 times, the time savings from copying 1,000 object references instead of having to copy 1,000 32-byte structures would likely outweigh the cost of creating the class object. If, however, the object instance would be abandoned after the reference has been copied only twice, the cost of creating the object would probably exceed by a large margin the cost of copying a 32-byte structure twice.

    Note also that it's possible in many cases to avoid passing around structures by value or otherwise redundantly copying them, if one endeavors to do so. Passing any size of structure as a ref parameter to a method, for example, only requires passing a single-machine-word (4 or 8 bytes) address. Because .net lacks any sort of const ref concept, only writable fields or variables may be passed that way, and the collections built into .net--other than System.Array--provide no means to access members by ref. If one is willing to use arrays or custom collections, however, even huge (100 bytes or more) structures can be processed very efficiently. In many cases, the performance advantage of using a structure rather than an immutable class may grow with the size of the encapsulated data.

    0 讨论(0)
  • 2020-11-29 07:50
    • Larger struct is not as efficient, but then.... if you HAVE more data, you have it. No sense talking about efficiency there.

    • 64 bytes should be OK.

    • The main reason possibly is copy operations.... which get IIRC slower if the struct is larger. And it must be copied around quite a lot.

    I would normally advice into using a class here ;) But without knowing the content of the struct, it is a little tricky.

    0 讨论(0)
  • 2020-11-29 07:55

    Actually, on a 64-bit machine 32 bytes is the maximum size to use for struct data. From my tests 32 byte struct (four longs) performs about as well as an object reference.

    You can find test code and run the tests yourself here: https://github.com/agileharbor/structBenchmark

    The last couple of tests copy a large number of structs/objects from one array to another, and you're able to see where class outperforms struct with eight longs, but it is about the same as struct with four longs.

    0 讨论(0)
提交回复
热议问题