问题
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 (for performance purposes).
Why exactly is this?
And (more important) can I have larger struct with same efficiency if I run my .NET 3.5 (soon to be .NET 4.0) 64-bit application on Core i7 under Windows 7 x64 (is this limitation CPU / OS based)?
Just to stress again - I need as efficient struct as it is possible. I try to keep it on the stack all the time. The application is heavily multi-threaded and runs on sub-millisecond intervals, and the current size of the struct is 64 bytes.
回答1:
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)
回答2:
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.
回答3:
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.
回答4:
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.
回答5:
One of the things I learnt while doing assembly language programming was that you align your structs (and other data) on 8 or 16 byte boundaries (there is actually a preprocessor command for it in MASM). The reason for this is considerably faster memory access when storing or moving things around in memory. Keeping your structs under 16 bytes in size would ensure that this memory alignment could be done successfully because nothing would cross the alignment boundaries.
However I would expect this sort of thing to be largely hidden from you when using the .NET framework. If your structs were bigger than 16 bytes then I would expect the framework (or JIT compiler) to align your data on 32 byte boundaries, and so on. It would be interesting to see some validation of the comments in those books, and see what the difference in speed is.
回答6:
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.
回答7:
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.
来源:https://stackoverflow.com/questions/2407691/why-is-16-byte-the-recommended-size-for-struct-in-c