.NET Memory size - c#

I have a pretty basic question about storing data and its memory footprint.
I have a List<t> that stores the base objects I need. The type t has an int id to define it, along with other fields.
I now have a Dictionary. If I create a Dictionary<t, int>, where t is the object for the value, will the memory allocation be much higher that if I create a Dictionary<int, int>, ie a copy of the t object is stored, or does only a refence to t get stored again?
Thanks

That depends on what T is. If T is a reference type (that is, a class), then only a reference will be stored in the dictionary. If T is a value type (a struct), then a copy will be stored.

Reference types do not create duplicate objects as you pass them around. Under the covers, basically you are passing around pointers. So if you have N objects, you will have N x memory per object + the memory required to reference each object. This is regardless of the storage container for those references, in your case, a dictionary. You'll incur some memory cost for the dictionary, but if you created another dictionary and put all the same objects in it, you would only have 2x Dictionary memory costs plus one set of objects in memory. This is when you are using reference types.
MyObject object = new MyObject(); // one object created in memory
MyObject object2 = object; // still only one object created in memory, but we have two references now
Value types are always unique in memory. So if you create a dictionary of System.Int32 and then create a duplicate of the dictionary, you will have a copy of each value in the dictionary as well.
int myInt = 5; // one int created in memory
int myInt2 = myInt; // two ints have been created in memory
So let's figure out what memory chunks are allocated for certain scenarios:
// two value types
Dictionary<int, int> myDictionary1 =
1 x Dictionary
N x int <key>
N x int <value>
Dictionary<int, int> myDictionary1 +
Dictionary<int,int> myDictionary2 (clone of 1) =
2 x Dictionary
2N x int <key>
2N x int <value>
// reference types
Dictionary <string, MyObject> myDictionary3 =
1 x Dictionary
N x string Reference
N x string instance (if they are all unique)
N x Object Reference
N x Object instance (if they are all unique)
Dictionary <string, MyObject> myDictionary3 +
Dictionary <string, MyObject> MyDictionary4 (clone of 3) =
2 x Dictionary
2N x string reference
1N x string instance (if they are all unique)
2N x Object reference
1N x Object instance (if they are all unqiue)
You're scenario:
Dictionary<int, MyObject> myDictionary5
1 X Dictionary
N X key
N X value reference
N X value object
Dictionary<int, MyObject> myDictionary5 +
Dictionary<int, MyObject> myDictionary6 (clone of 5) =
2 x Dictionary
2N x key
2N x value reference
1N x value objects

Only a reference to your object gets stored. Memory allocation will be small.

I assume you are talking about the specific collection type System.Collections.Generic.Dictionary<K,V>.
You didn't tell us whether your type 't' is a value type or a reference type.
If it is a reference type, e.g. class T { int id; ...}, then Dictionary<K,T> will keep references to the objects you added.
If it is a value type, e.g. struct T { int id; ...}, then Dictionary<K,T> will keep copies of the values you added.
Happy hacking.

As i mentioned in other question for profiling memory while developing you can use this code:
bool forceFullCollection = false;
Int64 valTotalMemoryBefore = System.GC.GetTotalMemory(forceFullCollection);
//call here your bulk of Dictionary operations and objects allocations
Int64 valTotalMemoryAfter = System.GC.GetTotalMemory(forceFullCollection);
Int64 valDifferenceMemorySize = valTotalMemoryAfter - valTotalMemoryBefore;
About parameter forceFullCollection: "If the forceFullCollection parameter is true, this method waits a short interval before returning while the system collects garbage and finalizes objects. The duration of the interval is an internally specified limit determined by the number of garbage collection cycles completed and the change in the amount of memory recovered between cycles. The garbage collector does not guarantee that all inaccessible memory is collected." GC.GetTotalMemory Method
Good luck!;)

Related

Is an empty variable has same size as filled variable in C#

This is fundamental question, I need to suppress memory use of my code in C#. I wonder if I initiate class A (let's say it have 10 variables) and I fill all variables with values. In another case I initiate class A and I fill only 2 variables with values, and let the rest is null or empty if it's a string. Will the first case has the higher memory consumptioon?
Probably. If a property of your class is a reference type, then if you assign to this property you will have some memory assigned because of that property.
Example:
class House{
object TV {get; set;}
}
If you do var house= new House(); you will use the space of house reference and Tv reference.
However if you do this:
var house= new House() {
TV= new {height= 100, width=1000}
};
it will take more since now the TV object takes space in addition to the TV reference. So you will have used extra space for height and width.
If you have a simple value type as a property:
class House{
int Price {get; set;}
}
It will not make any difference with
var house = new House();
or
var house = new House(){ Price=20000 };
That is because Price will be set to the int default value( which is 0), and every int takes the same space regardless of its value.
Yes, an empty variable has same size as filled variable in C# if variable is a value type or a reference: it takes the same memory space.
For example an int takes 4 bytes and long takes 8 bytes.
It the same for references, assigned or not.
A reference on x32 takes 4 bytes but in x64 it takes 8 bytes.
Each value type takes the size of the value with added the size of the hidden hidden pointer (the hidden reference).
When it is not the same size is for all types based on arrays like value[] and strings: in this case the initial size is the pointer size and then the space grows as the data is populated.
Hence the memory size of an array of int grows as you add integers, and it is the same as a string grows.
It is because it is sometimes preferable to use a StringBuilder instead of a String, and to avoid the use of ToList() for example when useless.
To this must be added the references of the methods and the virtual tables.
You can get the size of a serializable instance, excluding the reference and the methods tables, using:
using System.Runtime.Serialization.Formatters.Binary;
static public long SizeOf(object obj)
{
if ( obj == null ) return 0;
try
{
using ( MemoryStream stream = new MemoryStream() )
{
new BinaryFormatter().Serialize(stream, obj);
return stream.Length;
}
}
catch
{
return -1;
}
}

Memory Allocation for an Array of Struct and Class Object

Last day I was reading C# reference and there I saw a statement. Kindly have a look at the following statement.
Context:
the use of a struct rather than a class for a Point can make a large difference in the number of
memory allocations performed at run time. The program below creates and initializes an array of 100 points.
With Point implemented as a class, 101 separate objects are instantiated—one for the array and one each
for the 100 elements.
class Point
{
public int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
class Test
{
static void Main() {
Point[] points = new Point[100];
for (int i = 0; i < 100; i++)
points[i] = new Point(i, i*i);
}
}
If Point is instead implemented as a struct, as in
struct Point
{
public int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
only one object is instantiated—the one for the array. The Point instances are allocated in-line within the
array. This optimization can be misused. Using structs instead of classes can also make an application run slower or take up more memory, as passing a struct instance by value causes a copy of that struct to be
created.
Question:
Here my question is how memory allocation is done in case of Value Type and Reference Type?
Confusion:
Why it is mentioned in Reference Guide that Only 1 Object will be intialized. As per my understanding for each object in Array a separate memory will be allocated.
Edit: Possible Duplicate
This question is bit different from possible duplicate question as suggested by jason. My concern is about how memory is allocated in case of Value Type and Referenece Type solely while that question just explain the overview of Value Type and Reference Type.
Perhaps the difference between an array of a reference type and an array of a value type is easier to understand with an illustration:
Array of a reference type
Each Point as well as the array is allocated on the heap and the array stores references to each Point. In total you need N + 1 allocations where N is the number of points. You also need an extra indirection to access a field of a particular Point because you have to go through a reference.
Array of a value type
Each Point is stored directly in the array. There is only one allocation on the heap. Accessing a field does not involve indirection. The memory address of the field can be computed directly from the memory address of the array, the index of the item in the array and the location of the field inside the value type.
An array with reference types will consist of an array of references. Each reference points to a memory area which contains the actual object:
array[0] == ref0 -> robj0
array[1] == ref1 -> robj1
...
So there is one memory allocation for the array of references (size: arraylength * sizeof(reference)) and a separate memory allocation for each object (sizeof(robj)).
An array with value types (like structs) will contain just the objects:
array[0] == vobj0
array[1] == vobj1
...
so there is jst one memory allocation with size arraylength * sizeof(vobj)

LINQ Select Many - Modify flattened collection

I have a class named ACTIVITY. This class contains a list of Laps, and each Lap has a collection of TRACPOINTS.
ACTIVITY --many--> LAPS ---many --> TRACPOINTS.
Whenever I fLatten the TRACPOINTS collection I get the list of all the TRACPOINTS. But when I modify those of course the originals don't get modified since it's a copy.
Is there any way that whatever change I made to the flattened tracpoints gets changed in the Tracpoints list for each lap?
As long as TRACPOINT is a struct, it is not possible in any reasonable way.
Whenever you assign a value of struct variable or field to another variable or field, its contents are copied. The same holds for passing it as a method argument or returning it from a method, its value is copied. This is value semantics [1]. Compare this to atomic types like int, which have value semantics too. You would probably expect the following code to print 2, not 3.
static function Change(int j) { j = 3; }
static void Main(string[] args) {
int i = 2;
Change(i);
System.Console.WriteLine(i);
}
If you do SelectMany, each value from the collection is probably assigned to some temporary local variable and then returned from the iterator (SelectMany), therefore it is copied and in fact possibly copied many times before it comes out from the iterator. So what you are updating is a copy of the struct. Like in the example, you're not changing variable i, but its copy stored in variable j.
This is why structs should be immutable. Instead of having properties with getters and setter in your struct, they should have only getters. For changing values of properties of a struct, you can implement methods that copy the whole original struct, change the value of the desired property and return the new struct instance. In fact, again, its copy will be returned. Example:
struct S {
int f;
public int F { get { return this.f; } }
public S SetF(int newVal) {
var s = new S();
s.f = newVal;
return s;
}
}
var x = new S();
x = x.SetF(30);
That said, it could be possible to achieve what you want with pointers and unsafe C#, but believe me, it will be way easier to change your structs to classes, so that they have reference semantics instead of value semantics, or keep them structs, but make them immutable and do not use Linq, but old school loops. If you want to use Linq for something like SelectMany in such scenario, you probably do not care about performance difference between structs and classes so much...
[1] http://msdn.microsoft.com/en-us/library/aa664472(v=vs.71).aspx

Why is Interfaces behaviour different when using value types and reference types

I did the following example in c#
interface IChangeable
{
void Change(params Int32[] array);
}
struct SomeValueType : IChangeable
{
private Int32 m_X;
public SomeValueType(int X)
{
m_X = X;
}
public void Change(params Int32[] array)
{
m_X = array[0];
}
public override string ToString()
{
return String.Format("Crt value of m_X: {0}", m_X);
}
}
And in Main:
static void Main(String[] args)
{
SomeValueType someValueType = new SomeValueType(5);
Console.WriteLine(someValueType); // No boxing occured. It showed: 5
Object someRefType = someValueType; // Boxed
Console.WriteLine(someRefType); // Also Shows 5 (from heap)
someValueType.Change(2); // Change Value of x not o's
Console.WriteLine(someValueType + " " + someRefType); // 2 5
((SomeValueType)someRefType).Change(3); // Copies to a temp stack so no change ocuured in o
Console.WriteLine(someRefType); // 5
IChangeable itfStackChange = (IChangeable)someValueType;
itfStackChange.Change(7);
Console.WriteLine(someValueType); // Shows 2 and not 7 ... why?
IChangeable itfChange = (IChangeable)someRefType;
itfChange.Change(1); // Unboxes the value of o, making the value of x 1 boxes o again?
Console.WriteLine(someRefType); // Shows 1
}
Now I am wondering what happens when I do:
IChangeable itfStackChange = (IChangeable)someValueType; //value was 2 and its still 2
itfStackChange.Change(7);
Console.WriteLine(someValueType);
But if I change the definition of struct to class like in:
class SomeValueType : IChangeable
It writes 7 and not 2.
Value types semantics are such that the value gets copied on assignment. This means that when you change after assignment, the variables point to different objects.
For reference types the reference gets copied, meaning that when you change after assignment, both variables point to the same object.
See Value Types and Reference Types on MSDN.
A structure-type definition actually defines two kinds of things: a kind of storage location, and a kind of heap object which inherits from the abstract class System.ValueType. The heap object effectively has one field of the corresponding storage-location type, but exposes all the members of that storage-location type as though they were its own. To the outside world, the heap type will behave like a class object; internally, however, references to this are references to its field of the corresponding storage-location type.
Although C# defines the term "inheritance" in such a way as to pretend that the storage-location type and the heap-object type are one and the same, the two types will behave differently. Casting a value type to an interface that it represents will generate a new heap object which holds a copy of the public and private fields of the value type that was cast, and then return a reference to that new instance. The resulting reference will exhibit reference semantics, since it will be a reference.
If one regards heap objects and value-type storage locations as existing in separate universes, and recognizes the cases in which values must be copied from one universe to the other, one will find that such a model will accurately predict how things will behave.

How did the code achieve pass by reference?

Inside main i declared a local int[] array (int[] nums). I did not pass it by reference.
But when i print values of local array i get squared value of each element.
What is the reason for that?
delegate void tsquare(int[] a);
static void Main()
{
int[] nums = { 1, 2, 3 };
tsquare sqr = new tsquare(SomeClass.Square);
sqr(nums);
foreach (int intvals in nums)
{
Console.WriteLine(intvals);
}
}
class SomeClass
{
public static void Square(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
}
Update:
My appologies to all.What i tought is int[] {Array}is a value type,and the Delegate done
some trick on it.Now from your answer ,i understand Array is Reference type.
There are two concepts here.
Reference types vs. value types
Passing by value vs. passing by reference
Let's tackle the second one first.
Passing something by value means that you give the method its own copy of that value, and it's free to change that value however it wants to, without those changes leaking back into the code that called the method.
For instance, this:
Int32 x = 10;
SomeMethod(x); // pass by value
There's no way x is going to be anything other than 10 after the call returns in this case, since whatever SomeMethod did to its copy of the value, it only did to its own value.
However, passing by reference means that we don't really give the method its own value to play with, rather we give it the location in memory where our own value is located, and thus anything that method does to the value will be reflected back to our code, because in reality, there's only one value in play.
So this:
Int32 x = 10;
SomeMethod(ref x); // pass by reference
In this case, x might hold a different value after SomeMethod returns than it did before it was called.
So that's passing by value vs. passing by reference.
And now to muddle the waters. There's another concept, reference types vs. value types, which many confuses. Your question alludes to you being confused about the issue as well, my apologies if you're not.
A reference type is actually a two-part thing. It's a reference, and it's whatever the reference refers to. Think of a house you know the address of. You writing the address on a piece of paper does not actually put the entire house on that paper, rather you have a "reference" to that particular house on your piece of paper.
A reference type in .NET is the same thing. Somewhere in memory there is an object, which is a set of values, grouped together. The address of this object you store in a variable. This variable is declared to be a type which is a reference type, which allows this two-part deal.
The nice thing about reference types is that you might have many references to the same actual object, so even if you copy the reference around, you still only have one object in memory.
Edit: In respect to the question, an array is a reference type. This means that your variable only holds the address of the actual array, and that array object is located somewhere else in memory.
A value type, however, is one thing, the entire value is part of the "value type", and when you make copies of that, you make distinct copies
Here's an example of value types:
struct SomeType
{
public Int32 Value;
}
SomeType x = new SomeType;
x.Value = 10;
SomeType y = x; // value type, so y is now a copy of x
y.Value = 20; // x.Value is still 10
However, with a reference type, you're not making a copy of the object it refers to, only the reference to it. Think of it like copying the address of that house onto a second piece of paper. You still only have one house.
So, by simply changing the type of SomeType to be a reference type (changing struct to class):
class SomeType
{
public Int32 Value;
}
SomeType x = new SomeType;
x.Value = 10;
SomeType y = x; // reference type, so y now refers to the same object x refers to
y.Value = 20; // now x.Value is also 20, since x and y refer to the same object
And now for the final thing; passing a reference type by value.
Take this method:
public void Test(SomeType t)
{
t.Value = 25;
}
Given our class-version of SomeType above, what we have here is a method that takes a reference type parameter, but it takes it as being passed by value.
What that means is that Test cannot change t to refer to another object altogether, and make that change leak back into the calling code. Think of this as calling a friend, and giving him the address you have on your piece of paper. No matter what your friend is doing to that house, the address you have on your paper won't change.
But, that method is free to modify the contents of the object being referred to. In that house/friend scenario, your friend is free to go and visit that house, and rearrange the furniture. Since there is only one house in play, if you go to that house after he has rearranged it, you'll see his changes.
If you change the method to pass the reference type by reference, not only is that method free to rearrange the contents of the object being referred to, but the method is also free to replace the object with an altogether new object, and have that change reflect back into the calling code. Basically, your friend can tell you back "From now on, use this new address I'll read to you instead of the old one, and forget the old one altogether".
The array reference is passed by value automatically because it is a reference type.
Read:
Reference Types
Value Types
Most of the other answers are correct but I believe the terminology is confusing and warrants explanation. By default, you can say that all parameters in C# are passed by value, meaning the contents of the variable are copied to the method variable. This is intuitive with variables of value types, but the trick is in remembering that variables that are reference types (including arrays) are actually pointers. The memory location the pointer contains is copied to the method when it is passed in.
When you apply the ref modifier, the method gets the actual variable from the caller. For the most part the behavior is the same, but consider the following:
public void DoesNothing(int[] nums)
{
nums = new []{1, 2, 3, 4};
}
In DoesNothing, we instantiate a new int array and assign it to nums. When the method exits, the assignment is not seen by the caller, because the method was manipulating a copy of the reference (pointer) that was passed in.
public void DoesSomething(ref int[] nums)
{
nums = new []{1, 2, 3, 4};
}
With the ref keyword, the method can essentially reach out and affect the original variable itself from the caller.
To achieve what you seemed to originally want, you could create a new array and return it, or use Array.CopyTo() in the caller.
In C#, all parameters are passed by value by default. There are two kinds of types in C#, namely value and reference types.
A variable of reference type when passed as a parameter to a function will still be passed by value; that is if the function changes the object referred to by that variable, after the function completes the variable that was passed in will still refer to the same object (including null) as it did prior to calling the function in the same context.
However, if you use the ref modifier when declaring the function parameter than the function may change the object being referenced by the variable in the caller's context.
For Value types this is more straightforward but it is the same concept. Bear in mind, int[] is a reference type (as are all arrays).
Consider the differences in these functions when passing in some some array of ints:
public static void Square1(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
public static void Square2(int[] array)
{
array = {10, 20, 30};
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
public static void Square3(ref int[] array)
{
array = {10, 20, 30};
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
You're not passing it by reference. The array is being passed in by value, but arrays in .NET are reference types, so you're passing in a reference to the array, which is why you're seeing the values squared.
Read the following SO question - it explains the differences between pass-by-value and pass-by-reference. The accepted answer has a link in it to a good article about the topic that should help you understand the difference.
what is different between Passing by value and Passing by reference using C#
Arrays are objects and are passed by reference. Ints are structs and are passed by value (unless you use the ref keyword in your method signature as per the picky guy in the comments) (who was right) (but picky).

Categories

Resources