Structure performs better than the reference type (Class) with respect to CPU usage and memory usage. Consider using structure over class,
- If your application has to support data which does not require inheritance and interface
- The data is in large number
- The data is only of primitive data type like integer, byte, float, etc.
- Probability a graphics application or application which deals with large data
Note: Structure with large number of members will degrade the performance when passed as parameter/argument to functions because the values of the entire structure is copied as parameter/argument to the function.
Below code measures the creation of 100000 objects of a class and also measures the time taken to search an object from the collection.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Drawing;
namespace ClassTimeElapsed
{
class Brick
{
public int Id;
public float X;
public float Y;
public float Width;
public float Height;
public Color Color;
}
class Program
{
static void Main(string[] args)
{
Stopwatch objStopwatch;
Brick[] arrBrick;
int iCount;
iCount = 100000;
objStopwatch = new Stopwatch();
objStopwatch.Reset();
objStopwatch.Start();
arrBrick = new Brick[iCount];
for (int i = 0; i < iCount; i++)
{
arrBrick[i] = new Brick();
}
int iConst = 15;
for (int i = 0; i < iCount; i++)
{
arrBrick[i].Id = i + 1;
arrBrick[i].X = i * iConst;
arrBrick[i].Y = 0;
arrBrick[i].Width = 10;
arrBrick[i].Height = 10;
arrBrick[i].Color = Color.Teal;
}
objStopwatch.Stop();
Console.WriteLine(
"Class time elapsed for allocation and population");
//timeelapsed
Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
objStopwatch.Elapsed.TotalMilliseconds);
Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
objStopwatch.ElapsedMilliseconds);
int iSearchId = 99880;
Brick objBrick = null;
objStopwatch.Reset();
objStopwatch.Start();
for (int i = 0; i < arrBrick.Length; i++)
{
if (iSearchId == arrBrick[i].Id)
{
objBrick = arrBrick[i];
break;
}
}
objStopwatch.Stop();
Console.WriteLine(
"Class time elapsed for searching");
//search result
Console.WriteLine(
"search result: Id:{0},X:{1},Y:{2},Width:{3},Height:{4},Color:{5}",
objBrick.Id, objBrick.X, objBrick.Y, objBrick.Width, objBrick.Height,
objBrick.Color);
//timeelapsed
Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
objStopwatch.Elapsed.TotalMilliseconds);
Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
objStopwatch.ElapsedMilliseconds);
Console.ReadLine();
}
}
}
Output:
Class time elapsed for allocation and population
TimeElapsed (Stopwatch float):13.7327ms
TimeElapsed (Stopwatch rounded):13ms
Class time elapsed for searching
search result: Id:99880,X:1498185,Y:0,Width:10,Height:10,Color:Color [Teal]
TimeElapsed (Stopwatch float):1.3015ms
TimeElapsed (Stopwatch rounded):1ms
Below code measures the creation of 100000 objects of a struct and also measures the time taken to search an object from the collection.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Drawing;
namespace StructTimeElapsed
{
struct Brick
{
public int Id;
public float X;
public float Y;
public float Width;
public float Height;
public Color Color;
}
class Program
{
static void Main(string[] args)
{
Stopwatch objStopwatch;
Brick[] arrBrick;
int iCount;
iCount = 100000;
objStopwatch = new Stopwatch();
objStopwatch.Reset();
objStopwatch.Start();
arrBrick = new Brick[iCount];
int iConst = 15;
for (int i = 0; i < iCount; i++)
{
arrBrick[i].Id = i + 1;
arrBrick[i].X = i * iConst;
arrBrick[i].Y = 0;
arrBrick[i].Width = 10;
arrBrick[i].Height = 10;
arrBrick[i].Color = Color.Teal;
}
objStopwatch.Stop();
Console.WriteLine(
"Struct time elapsed for allocation and population");
//timeelapsed
Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
objStopwatch.Elapsed.TotalMilliseconds);
Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
objStopwatch.ElapsedMilliseconds);
int iSearchId = 99880;
Brick objBrick;
objBrick.Id = 0;
objBrick.X = 0;
objBrick.Y = 0;
objBrick.Width = 0;
objBrick.Height = 0;
objBrick.Color = Color.Transparent;
objStopwatch.Reset();
objStopwatch.Start();
for (int i = 0; i < arrBrick.Length; i++)
{
if (iSearchId == arrBrick[i].Id)
{
objBrick = arrBrick[i];
break;
}
}
objStopwatch.Stop();
Console.WriteLine(
"Struct time elapsed for searching");
//search result
Console.WriteLine(
"search result: Id:{0},X:{1},Y:{2},Width:{3},Height:{4},Color:{5}",
objBrick.Id, objBrick.X, objBrick.Y, objBrick.Width, objBrick.Height,
objBrick.Color);
//timeelapsed
Console.WriteLine("TimeElapsed (Stopwatch float):{0}ms",
objStopwatch.Elapsed.TotalMilliseconds);
Console.WriteLine("TimeElapsed (Stopwatch rounded):{0}ms",
objStopwatch.ElapsedMilliseconds);
Console.ReadLine();
}
}
}
Output:
Struct time elapsed for allocation and population
TimeElapsed (Stopwatch float):3.0684ms
TimeElapsed (Stopwatch rounded):3ms
Struct time elapsed for searching
search result: Id:99880,X:1498185,Y:0,Width:10,Height:10,Color:Color [Teal]
TimeElapsed (Stopwatch float):1.0981ms
TimeElapsed (Stopwatch rounded):1ms
Below code measures the memory usage of creation of 100000 objects of a class.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Drawing;
namespace ClassMemoryUsage
{
class Brick
{
public int Id;
public float X;
public float Y;
public float Width;
public float Height;
public Color Color;
}
class Program
{
static void Main(string[] args)
{
long lngGCMemStart = 0;
long lngGCMemEnd = 0;
long lngProcessMemStart = 0;
long lngProcessMemEnd = 0;
Brick[] arrBrick;
int iCount;
iCount = 100000;
Process objProcess = Process.GetCurrentProcess();
//Measure starting point memory
lngGCMemStart = System.GC.GetTotalMemory(true);
lngProcessMemStart = objProcess.PrivateMemorySize64;
arrBrick = new Brick[iCount];
for (int i = 0; i < iCount; i++)
{
arrBrick[i] = new Brick();
}
//Measure memory after allocating
lngGCMemEnd = System.GC.GetTotalMemory(true);
lngProcessMemEnd = objProcess.PrivateMemorySize64;
int iConst = 15;
for (int i = 0; i < iCount; i++)
{
arrBrick[i].Id = i+1;
arrBrick[i].X = i*iConst;
arrBrick[i].Y = 0;
arrBrick[i].Width = 10;
arrBrick[i].Height = 10;
arrBrick[i].Color = Color.Teal;
}
Console.WriteLine("Class memory usage.");
//memoryusage difference
Console.WriteLine("GC Memory Use:{0} (bytes)",
lngGCMemEnd - lngGCMemStart);
Console.WriteLine("Process Memory Use:{0} (bytes)",
lngProcessMemEnd - lngProcessMemStart);
Console.WriteLine("GC Memory Start:{0} (bytes)",
lngGCMemStart.ToString());
Console.WriteLine("Process Memory Start:{0} (bytes)",
lngProcessMemStart.ToString());
Console.WriteLine("GC Memory End:{0} (bytes)",
lngGCMemEnd.ToString());
Console.WriteLine("Process Memory End:{0} (bytes)",
lngProcessMemEnd.ToString());
Console.ReadLine();
}
}
}
Output:
Class memory usage.
GC Memory Use:4802368 (bytes)
Process Memory Use:0 (bytes)
GC Memory Start:130648 (bytes)
Process Memory Start:9232384 (bytes)
GC Memory End:4933016 (bytes)
Process Memory End:9232384 (bytes)
Below code measures the memory usage of creation of 100000 objects of a struct.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Drawing;
namespace StructMemoryUsage
{
struct Brick
{
public int Id;
public float X;
public float Y;
public float Width;
public float Height;
public Color Color;
}
class Program
{
static void Main(string[] args)
{
long lngGCMemStart = 0;
long lngGCMemEnd = 0;
long lngProcessMemStart = 0;
long lngProcessMemEnd = 0;
Brick[] arrBrick;
int iCount;
iCount = 100000;
Process objProcess = Process.GetCurrentProcess();
//Measure starting point memory
lngGCMemStart = System.GC.GetTotalMemory(true);
lngProcessMemStart = objProcess.PrivateMemorySize64;
arrBrick = new Brick[iCount];
//Measure memory after allocating
lngGCMemEnd = System.GC.GetTotalMemory(true);
lngProcessMemEnd = objProcess.PrivateMemorySize64;
int iConst = 15;
for (int i = 0; i < iCount; i++)
{
arrBrick[i].Id = i + 1;
arrBrick[i].X = i * iConst;
arrBrick[i].Y = 0;
arrBrick[i].Width = 10;
arrBrick[i].Height = 10;
arrBrick[i].Color = Color.Teal;
}
Console.WriteLine("Struct memory usage.");
//memoryusage difference
Console.WriteLine("GC Memory Use:{0} (bytes)",
lngGCMemEnd - lngGCMemStart);
Console.WriteLine("Process Memory Use:{0} (bytes)",
lngProcessMemEnd - lngProcessMemStart);
Console.WriteLine("GC Memory Start:{0} (bytes)",
lngGCMemStart.ToString());
Console.WriteLine("Process Memory Start:{0} (bytes)",
lngProcessMemStart.ToString());
Console.WriteLine("GC Memory End:{0} (bytes)",
lngGCMemEnd.ToString());
Console.WriteLine("Process Memory End:{0} (bytes)",
lngProcessMemEnd.ToString());
Console.ReadLine();
}
}
}
Output:
Struct memory usage.
GC Memory Use:3602368 (bytes)
Process Memory Use:0 (bytes)
GC Memory Start:130656 (bytes)
Process Memory Start:9232384 (bytes)
GC Memory End:3733024 (bytes)
Process Memory End:9232384 (bytes)
Why?
Structure is created in the stack.Structure is a value type.
Rule: Consider using structure for supporting large number of objects(data) in your application.