C# basics - Memory Management - c#

I am new to the programming in C#.
Can anyone please tell me memory management about C#?
Class Student
{
int Id;
String Name;
Double Marks;
public string getStudentName()
{
return this.Name;
}
public double getPersantage()
{
return this.Marks * 100 / 500;
}
}
I want to know how much memory is allocated for instance of this class?
What about methods? Where they are allocated?
And if there are static methods, what about their storage?
Can anyone please briefly explain this to me?

An instance of the class itself will take up 24 bytes on a 32-bit CLR:
8 bytes of object overhead (sync block and type pointer)
4 bytes for the int
4 bytes for the string reference
8 bytes for the double
Note that the memory for the string itself is in addition to that - but many objects could share references to the same string, for example.
Methods don't incur the same sort of storage penalty is fields. Essentially they're associated with the type rather than an instance of the type, but there's the IL version and the JIT-compiled code to consider. However, usually you can ignore this in my experience. You'd have to have a large amount of code and very few instances for the memory taken up by the code to be significant compared with the data. The important thing is that you don't get a separate copy of each method for each instance.
EDIT: Note that you happened to pick a relatively easy case. In situations where you've got fields of logically smaller sizes (e.g. short or byte fields) the CLR chooses how to lay out the object in memory, such that values which require memory alignment (being on a word boundary) are laid out appropriately, but possibly backing other ones - so 4 byte fields could end up taking 4 bytes, or they could take 16 if the CLR decides to align each of them separately. I think that's implementation-specific, but it's possible that the CLI spec dictates the exact approach taken.

As, I think Jon Skeet is saying, it depends on a lot of factors, and not easily measurable ahead of time. Factors such as whether it's running on a 64 bit OS or 32 bit OS must be taken into account, and whether you are running a debug or release version come into play. The amount of memory taken up by code depends on the processor that the JITTER compiles to, as different optimizations can be used for different processors.

Not really answer, just for fun.
struct Student
{
int Id;
[MarshalAs(UnmanagedType.LPStr)]
String Name;
Double Marks;
public string getStudentName()
{
return this.Name;
}
public double getPersantage()
{
return this.Marks * 100 / 500;
}
}
And
Console.WriteLine(Marshal.SizeOf(typeof(Student)));
On 64bit return:
24
And on 32 bit:
16

sizeof(getPersantage());
a good way to find out bytes for it. not too havent done much C#, but better with an answer than no answer :=)

Related

Store data inside long number or class instance for better performance

I'm writing an AI for my puzzle game and I'm facing the following situation:
Currently, I have a class, Move, which represents a move in my game, which has similiar logic to chess.
In the Move class, I'm storing the following data:
The move player color.
The moving piece.
The origin position on the board.
The destination position on the board.
The piece that has been killed by performing this move (if any).
The move score.
In addition, I got some methods which describes amove, such as IsResigned, Undo etc.
This move instance is being passed along in my AI, which is based on the Alpha Beta algorithm. Therfore, the move instance is being passed many times, and I'm constructing many many Move class instances along the AI implementation. Thus, I'm afriad that it may have significant inpact of the performance.
To reduce the performance inpact, I thought about the following solution:
Instead of using instances of the Move class, I'll store my entire move data inside a long number (using bitwise operations), and then will extract the information as needed.
For instance:
- Player color will be from bit 1 - 2 (1 bit).
- Oirign position will be from bit 2 - 12 (10 bits).
and so on.
See this example:
public long GenerateMove(PlayerColor color, int origin, int destination) {
return ((int)color) | (origin << 10) | (destination << 20);
}
public PlayerColor GetColor(long move) {
return move & 0x1;
}
public int GetOrigin(long move) {
return (int)((move >> 10) & 0x3f);
}
public int GetDestination(long move) {
return (int)((move >> 20) & 0x3f);
}
Using this method, I can pass along the AI just long numbers, instead of class instances.
However, I got some wonders: Put aside the added complexity to the program, class instances are being passed in C# by reference (i.e. by sending a pointer to that address). So does my alternative method even make sense? The case is even worse, since I'm using long numbers here (64bis), but the pointer address may be represented as an integer (32bits) - so it may even have worest performance than my current implementation.
What is your opinion about this alternative method?
There are a couple of things to say here:
Are you actually having performance problems (and are you sure memory usage is the reason)? Memory allocation for new instances is very cheap in .net and normally, you will not notice garbage collection. So you might be barking up the wrong tree here.
When you pass an instance of a reference type, you are just passing a reference; when you store a reference type (e.g. in an array), you will just store the reference. So unless you create a lot of distinct instances or copy the data into new instances, passing the reference does not increase heap size. So passing references might be the most efficient way to go.
If you create a lot of copies and discard them quickly and you are afraid of memory impact (again, do you face actual problems?), you can create value types (structinstead of class). But you have to be aware of the value type semantics (you are always working on copies).
You can not rely on a reference being 32 bit. On a 64 bit system, it will be 64 bit.
I would strongly advise against storing the data in an integer variable. It makes your code less maintainable and that is in most of the cases not worth the performance tradeoff. Unless you are in severe trouble, don't do it.
If you don't want to give up on the idea of using a numeric value, use at least a struct, that is composed of two System.Collections.Specialized.BitVector32 instances. This is a built in .NET type that will do the mask and shift operations for you. In that struct you can also encapsulate accessing the values in properties, so you can keep this rather unusual way of storing your values away from your other code.
UPDATE:
I would recommend you use a profiler to see where the performance problems are. It is almost impossible (and defenitely not a good use of your time) to use guesswork for performance optimization. Once you see the profiler results, you'll probably be surprised about the reason of your problems. I would bet that memory usage or memory allocation is not it.
In case you actually come to the conclusion that memory consumption of your Move instances is the reason and using small value types would solve the problem (I'd be surprised), don't use an Int64, use a custom struct (as described in 6.) like the following, that will be the same size as an Int64:
[System.Runtime.InteropServices.StructLayout( System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 4 )]
public struct Move {
private static readonly BitVector32.Section SEC_COLOR = BitVector32.CreateSection( 1 );
private static readonly BitVector32.Section SEC_ORIGIN = BitVector32.CreateSection( 63, SEC_COLOR );
private static readonly BitVector32.Section SEC_DESTINATION = BitVector32.CreateSection( 63, SEC_ORIGIN );
private BitVector32 low;
private BitVector32 high;
public PlayerColor Color {
get {
return (PlayerColor)low[ SEC_COLOR ];
}
set {
low[ SEC_COLOR ] = (int)value;
}
}
public int Origin {
get {
return low[ SEC_ORIGIN ];
}
set {
low[ SEC_ORIGIN ] = value;
}
}
public int Destination {
get {
return low[ SEC_DESTINATION ];
}
set {
low[ SEC_DESTINATION ] = value;
}
}
}
But be aware that you are now using a value type, so you have to use it accordingly. That means assignments create copies of the original (i.e. changing the destination value will leave the source unchanged), using ref parameters if you want to persist changes made by subroutines and avoid boxing at any cost to prevent even worse performance (some operations can mean boxing even though you won't immediately notice, e.g. passing the struct that implements an interface as an argument of the interface type). Using structs (just as well as using Int64) will only be worth it when you create a lot of temporary values, which you quickly throw away. And then you'll still need to confirm with a profile that your performance is actually improved.

Reducing memory pressure with many small classes

I am struggling with memory problems in some legacy code.
The code performs various tasks with huge point clouds, all based around the following data structure:
public class Point
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
}
At any time, a couple millions of these points may hang around in memory in various lists. Many of these stay in memory long enough to go into generation 2 of the garbage collection. Since the program runs in 32bit mode, virtual address space is limited.
The programs using this legacy code sometimes crash with OutOfMemoryExceptions. Even if they do not crash, they consume far more memory than they should, and virtual address space is frequently fragmented to the point where no continuous chunk of memory larger than 50mb is available (e.g. MemoryFailPoint(50) fails). A couple of methods have explicit calls to GC.Collect(), and removing those increases the frequency of the crashes.
Now, I know of a two ways to solve this problem, both of which I cannot use:
Use a struct instead of a class for the points. Do not store those structs within a List, instead use arrays, to avoid copying the points with each access. Structs have far less overhead per instance than classes, and do not bother the garbage collector as much.
Unfortunately this would require huge breaking changes to the code; the existing methods all expect the point class to be mutable, and references to individual points are passed around everywhere. The copy-by-value semantics of structs will cause all sorts of problems.
Switch the whole app to 64bit. This would not reduce the memory, but would increase the virtual address space to a point where at least the app would not crash anymore.
Unfortunately there are a couple of legacy 32bit dlls that prevent this.
Is there any other way I could keep working with the existing Point class in 32bit, but reduce memory pressure and ease work for the garbage collector?
Can I somehow allocate and free all those points myself in unmanaged memory, while still passing references around in managed code?
Or is there another workaround I have missed?
In your comment, you already achieved significant improvement from 36 bytes down to 24 bytes by going from double to float:
I did some tests with float instead of double: I was able to save 33%
( the original point class is 24 byte + 12 byte overhead, with floats
it is 12 byte + 12 byte overhead.) With a struct I could save another
12 bytes for the class overhead. – HugoRune Sep 20 '16 at 16:19
You can get an additional 8 byte improvement by encapsulating a struct in your objects, and this achieves 16 bytes per Point (12 bytes for the floats with 4 bytes overhead), and saves an additional 22% for a total of 55%:
public struct PointFloat
{
public float X;
public float Y;
public float Z;
}
public class Point
{
private PointFloat dbls;
public float X
{
get { return dbls.X; }
set { dbls.X = value; }
}
public float Y
{
get { return dbls.Y; }
set { dbls.Y = value; }
}
public float Z
{
get { return dbls.Z; }
set { dbls.Z = value; }
}
}

What are layout and size of a managed class's header in unmanaged memory?

Recently, in this question, I've asked how to get a raw memory address of class in C# (it is a crude unreliable hack and a bad practice, don't use it unless you really need it). I've succeeded, but then a problem arose: according to this article, first 2 words in the class raw memory representation should be pointers to SyncBlock and RTTI structures, and therefore the first field's address must be offset by 2 words [8 bytes in 32-bit systems, 16 bytes in 64-bit systems] from the beginning. However, when I dump first bytes from memory at the object location, first field's raw offset from the object's address is only 1 32-bit word (4 bytes), which doesn't make any sense for both types of systems. From the question I've linked:
class Program
{
// Here is the function.
// I suggest looking at the original question's solution, as it is
// more reliable.
static IntPtr getPointerToObject(Object unmanagedObject)
{
GCHandle gcHandle = GCHandle.Alloc(unmanagedObject, GCHandleType.WeakTrackResurrection);
IntPtr thePointer = Marshal.ReadIntPtr(GCHandle.ToIntPtr(gcHandle));
gcHandle.Free();
return thePointer;
}
class TestClass
{
uint a = 0xDEADBEEF;
}
static void Main(string[] args)
{
byte[] cls = new byte[16];
var test = new TestClass();
var thePointer = getPointerToObject(test);
Marshal.Copy(thePointer, cls, 0, 16); //Dump first 16 bytes...
Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(thePointer.ToInt32())));
Console.WriteLine(BitConverter.ToString(cls));
Console.ReadLine();
gcHandle.Free();
}
}
/* Example output (yours should be different):
40-23-CA-02
4C-38-04-01-EF-BE-AD-DE-00-00-00-80-B4-21-50-73
That field's value is "EF-BE-AD-DE", 0xDEADBEEF as it is stored in memory. Yay, we found it!
*/
Why is so? Maybe I've just got the address wrong, but how and why? And if I didn't, what could be wrong anyway? Maybe, if that article is wrong, I simply misunderstood what managed class header looks like? Or maybe it doesn't have that Lock pointer - but why and how is this possible?..
(These are, obviously, only a few possible options, and, while I'm still going to carefully check each one I can predict, wild guessing cannot compare in both time and accuracy to a correct answer.)
#HansPassant brilliantly pointed out that the pointer for the object in question points to the second structure, the method table. Now that totally makes sense for performance reasons, as the method table (RTTI structure) is used far more often than the SyncRoot structure, which, therefore, is still located right before it at the negative index -1.
He made it clear that he doesn't want to post this answer so I'm posting it myself, but the credit still goes to him.
But I would like to remind that this is a dirty unreliable hack, possibly making the system unstable:
Beyond the pinning problem, other nasty issues are not having any idea how long the object is and how the fields are arranged.
You should use the debugger instead, unless you understand all the consequences, understand exactly what you are trying to do and really need to do it - using this, dirty and unreliable, way.

Class vs Struct

Using these two as references
Immutable class vs struct
http://msdn.microsoft.com/en-us/library/ms229017(v=vs.110).aspx
I wonder what is recommended in my case (and preferably why). I am currently building an inventory manager, add, delete, move, remove Item. (Will later have equip/unequip as well, but they do not directly integrate with my inventory, as the inventory will only manage the remove (for equip) and add (for unequip)
So either a class or a struct, that is the question!
One person points out a 8 byte limit, msdn says 16. By Item class will hold a lot more than that.
private string _name;
private string _desc;
private bool _dropable;
private int _price;
private int _maxQuantity;
My ItemSlot struct/class will have an Item (or an int _itemId) as well as a quantity. Which should (yes?) add up to well over 16 bytes.
private ItemSlot[] _inventory;
public const int INVENTORY_SIZE = 50;
public Party () {
ItemSlot[] _inventory = new ItemSlot[INVENTORY_SIZE];
}
The tutorial series I am trying to follow uses a struct, however; now with this knowledge am I correct in that I should have a class for the item slots? Or is my understanding all to shallow?
Go with a class.
The recommended sizes for structs isn't because of available memory (yes, memory is cheap these days as pointed out by Arun in the comments).. but the real reason is because structs are copied by value. This means that every time you pass your structure around.. every field is copied along with it. So, the "struct byte-limit" recommendations you're seeing everywhere is to avoid that.
A class on the other hand, only copies the value of a reference.. which is the native word size of the processor it is running on .. making the copy operation barely measurable.
You stated your structure is going to be much bigger than 16 bytes.. that is definitely reason enough to go with a class purely to avoid the overhead of copying around entire blocks of memory when using a struct.
As others mentioned: Don't worry about memory usage so much. Or rather: Worry about memory usage where it matters.
But what really matters: A class is flexible are struct is not. It you need to add some logic to your data later on, this is possible with a class, but not with a struct. E.g. a class can have a method, but not a struct.
This can be a huge headache, I have often thought "damn now I have to provide a method which does some task and now I have to change this struct to class".
So my rule of thumb is:
Use a struct only when: There is no foreseeable need for methods or complex getters / setters AND the data are very small and are unlikely to grow.
The "and clause" comes from the fact that complex structures are getting a method in the future, regardless what you are thinking now.
If you look into the net framework, classes are used almost everywhere, where structs are only used for very small related data like a Point (x and y coordinates)

.NET, get memory used to hold struct instance

It's possible to determine memory usage (according to Jon Skeet's blog)
like this :
public class Program
{
private static void Main()
{
var before = GC.GetTotalMemory(true);
var point = new Point(1, 0);
var after = GC.GetTotalMemory(true);
Console.WriteLine("Memory used: {0} bytes", after - before);
}
#region Nested type: Point
private class Point
{
public int X;
public int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}
#endregion
}
It prints Memory used: 16 bytes (I'm running x64 machine).
Consider we change Point declaration from class to struct. How then to determine memory used? Is is possible at all? I was unable to find anything about getting stack size in .NET
P.S
Yes, when changed to 'struct', Point instances will often be stored on Stack(not always), instead of Heap.Sorry for not posting it first time together with the question.
P.P.S
This situation has no practical usage at all(IMHO), It's just interesting for me whether it is possible to get Stack(short term storage) size. I was unable to find any info about it, so asked you, SO experts).
You won't see a change in GetTotalMemory if you create the struct the way you did, since it's going to be part of the thread's stack, and not allocated separately. The GetTotalMemory call will still work, and show you the total allocation size of your process, but the struct will not cause new memory to be allocated.
You can use sizeof(Type) or Marshal.SizeOf to return the size of a struct (in this case, 8 bytes).
There is special CPU register, ESP, that contains pointer to the top of the stack. Probably you can find a way to read this register from .Net (using some unsafe or external code). Then just compare value of this pointer at given moment with value at thread start - and difference between them will be more or less acurate amount of memory, used for thread's stack. Not sure if it really works, just an idea :)
In isolation, as you have done here, you might have a "reasonable" amount of success with this methodology. I am not confident the information is useful, but running this methodology, especially if you run it numerous times to ensure you did not have any other piece of code or GC action affecting the outcome. Utilizing this methodology in a real world application is less likely to give accurate results, however, as there are too many variables.
But realize, this only "reasonable" and not a surety.
Why do you need to know the size of objects? Just curious, as knowing the business reason may lead to other alternatives.

Categories

Resources