Thursday, June 17, 2010

C# measurement tools

There are two important factor which has to be measured to identify the improvement in the code
  • Time taken to complete some operation
  • Memory usage of the application
Below is the code for measuring memory consumption.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace StructMemoryUsage
{
    struct EmployeeStruct
    {
        public string Name;
        public int EmpId;
    }

    class Program
    {
        static void Main(string[] args)
        {
            long lngGCMemStart = 0;
            long lngGCMemEnd = 0;
            long lngProcessMemStart = 0;
            long lngProcessMemEnd = 0;

            //employee as struct
            EmployeeStruct[] objEmployee;
            int iCount;
            iCount = 100000;

            Process objProcess = Process.GetCurrentProcess();
            //Measure starting point memory
            lngGCMemStart = System.GC.GetTotalMemory(true);
            lngProcessMemStart = objProcess.PrivateMemorySize64;

            objEmployee = new EmployeeStruct[iCount];

            //Measure memory after allocating
            lngGCMemEnd = System.GC.GetTotalMemory(true);
            lngProcessMemEnd = objProcess.PrivateMemorySize64;

            for (int i = 0; i < iCount; i++)
            {
                objEmployee[i].Name = "Emp" + i.ToString();
                objEmployee[i].EmpId = i;
            }
            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:802380 (bytes)
Process Memory Use:0 (bytes)
GC Memory Start:126592 (bytes)
Process Memory Start:8937472 (bytes)
GC Memory End:928972 (bytes)
Process Memory End:8937472 (bytes)

Note: Alternatively use perfmon->Add Counters->.NET CLR Memory counters can be used for viewing the memory consumption of selected .NET process.

Below is the code for measuring the time.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace MeasuringTime
{
    class Program
    {
        static void Main(string[] args)
        {
            long lngStartTime = 0;
            long lngEndTime = 0;
            DateTime dtStartTime;
            TimeSpan tsTimeDiff;
            long lngSWFrequency=0;
            Stopwatch objSW;// Only from .Net 2.0

            //If the computer is kept running continuously
            //for 49 days then the Environment.TickCount would
            //start counting backwards
            //So the most significant bit is extracted
            lngStartTime = Environment.TickCount
                & Int32.MaxValue;
            System.Threading.Thread.Sleep(5000);
            lngEndTime = Environment.TickCount
                & Int32.MaxValue;

            Console.WriteLine("TimeElapsed (TickCount):{0}ms",
                lngEndTime - lngStartTime);
            //Resolution of DateTime.Now is 10+ milliseconds
            dtStartTime = DateTime.Now;
            System.Threading.Thread.Sleep(5000);
            tsTimeDiff = DateTime.Now - dtStartTime;


            Console.WriteLine("TimeElapsed (DateTime):{0}ms",
                tsTimeDiff.TotalMilliseconds);
            //Stopwatch uses the hardware timer if it
            //highresolution timer or else uses the DateTime.Now
            //To check the availability of the high
            //resolution timer use IsHighResolution property
            if (true == Stopwatch.IsHighResolution)
            {
                Console.WriteLine(
                    "HighResolutionTimer is present"
                    );
            }
            else
            {
                Console.WriteLine(
                    "HighResolutionTimer is absent"
                    );
            }

            lngSWFrequency = Stopwatch.Frequency;
            Console.WriteLine(
                "Timer frequency in ticks/second:{0}",
                lngSWFrequency);
            objSW = Stopwatch.StartNew();
            System.Threading.Thread.Sleep(5000);
            objSW.Stop();
            Console.WriteLine(
                "TimeElapsed (Stopwatch float):{0}ms",
                objSW.Elapsed.TotalMilliseconds
                );
            Console.WriteLine(
                "TimeElapsed (Stopwatch rounded):{0}ms",
                objSW.ElapsedMilliseconds
                );

            Console.ReadLine();

        }
    }
}

Output:
TimeElapsed (TickCount):4992ms
TimeElapsed (DateTime):5002ms
HighResolutionTimer is present
Timer frequency in ticks/second:14318180
TimeElapsed (Stopwatch float):5000.7317ms
TimeElapsed (Stopwatch rounded):5000ms

Note: Profiling tools can be used for the measuring time and memory leak.

No comments: