Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the C# 16 Byte struct limitation mean I can't use strings in structs?

Tags:

string

c#

struct

I have a struct:

public struct MyStruct
{
    public readonly string Str1;
    public readonly string Str2;
}

According to the Internet, you really should only use structs if their size is 16 bytes or less. If more, performance issues can happen. From various searches, a string stores 2 bytes per character. This means that if you have a string in a struct, it could only have 8 characters at most, assuming it's the only string in your struct. In my example, that'd be split among both fields I have.

Elsewhere, however, I've read that only the string reference is put in the struct, not the string itself.

My question is: Does the 16 byte recommendation/limitation of C# structs mean that I basically can't use strings in them. I like taking advantage of structs sometimes (especially the cannot-be-null parts of it), so I want to know if there's still a way to use them while following the recommendations.

EDIT: Poor choice of words on my part. Indeed it's not a limitation of the language, but rather a recommendation based on performance to not exceed 16 bytes in one's structs. I think I'm falling victim to premature optimization here: Perhaps I should only worry about this limitation if I see actual performance problems in my application, rather than fretting over small numbers of bytes.

like image 444
Doctor Blue Avatar asked Jul 11 '14 15:07

Doctor Blue


People also ask

Which is positive C or T?

One coloured line should be in the control line region (C), and another coloured line should be in the test line region (T). Two lines, one next to C and one next to T, even faint lines, show the test is positive.

What does the C and T mean on the lateral flow test?

This is what the test “window” looks like in the strip after 30 minutes. “C” stands for “control” – this is to make sure the test is working. “T” stands for “test” – this is where your sample result will appear. Image © https://www.gov.uk/ Negative result: one line next to C shows the test is negative.

Is C or T positive on Covid test?

For most positive tests, a reddish-purple line will appear in the Control (C) Zone and the Test (T) Zone; however, in cases where the viral load in the sample is very high, the line in the Control (C) Zone may not be present or may be very faint.

What does a faint T line mean on Covid test?

This indicates the test is negative. Two lines – even faint lines – indicate the test is positive. The test has failed and should be retaken. Negative result.


2 Answers

Advice regarding the 16-byte threshold should be considered out of date. The .NET Runtime optimizes operations on structures below a certain size (which used to be 16 bytes, but has since increased to I think 24); the cost per byte increases when structures exceed that size, but that doesn't mean one should use a class for everything larger than that.

The cost of creating a new structure is proportional to its size. The cost of creating a new class object is proportional to its size plus some significant additional overhead. The cost of copying an existing structure is proportional to its size, with a penalty for structs over a certain size. The cost of copying a reference to an immutable class object is fixed and small.

Creating a structure of any size and copying it once or twice will always be cheaper than creating a class object of the same size and copying the reference likewise. If the structure or class reference would get copied millions of times, even a 12-byte class might outperform a 12 byte structure. For values in between, the break-even size for class vs. structure will depend upon the number of times a struct or class reference would get copied, but unless a type is really big or would be copied many thousands of times, the extra cost to copy structures will still be cheaper than the extra cost to create class objects.

With regard to the fact that a structure contains strings, one should regard a reference to an immutable-type object as having a cost of 4 or 8 bytes on a 32-bit or 64-bit system. Since a string field does not "hold" a string but merely identifies one, a struct with two string fields would thus take 8 or 16 bytes, regardless of the lengths of the strings identified thereby.

like image 148
supercat Avatar answered Nov 08 '22 19:11

supercat


String is a reference type, so in this case, you are only holding 2 references to your two strings however long they are. The 2 references, are 4 bytes each on a 32-bit system, and 8 byte each on a 64-bit system. They contain the memory address of your strings.

The guideline of this 16 byte struct limitation is probably because when you are passing a struct (vs. a class), the values get copied. If the struct is large, then a lot of memory copying will be done, which will negatively impact the performance.

like image 35
user1032613 Avatar answered Nov 08 '22 19:11

user1032613