Monday 17 December 2012

NP Profiler


Recently came across a very useful profiling tool – NP.NET profiler. Apart from providing profiling capability for standard .NET based windows and web applications, a separate version of NP profiler allows to profile Windows Store Applications as well.  And it is available for free!!

Here is the overview from the tool’s website:

NP .NET Profiler Tool is designed to assist in troubleshooting issues such as slow performance, memory related issues, and first chance exceptions in .NET applications.

It can troubleshoot following types of .NET applications:

  • Windows Store Applications
  • ASP.NET Web Applications
  • .NET Windows Applications (WCF, WPF and WF )
  • .NET Console Applications
  • .NET Window Services
  • .NET COM+ Components
  • Azure Service

Wednesday 28 November 2012

Game of Life


Here is one small attempt to write a program that runs Conway's Game Of Life. 
It is a zero player game which does not require any user input once it has been started with 
an initial configuration. It is basically an infinite 2-D array of cells, each cell having 
state of either being alive (1) or being dead (0). At each step (tick of time), state of 
cell changes based on 4 simple rules (referred from aforementioned wikipedia article) -
  • Any live cell with fewer than two live neighbours dies, as if caused by under-population.
  • Any live cell with two or three live neighbours lives on to the next generation.
  • Any live cell with more than three live neighbours dies, as if by overcrowding.
  • Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
Below is a simple C# console application that runs Game of life. It is by no means
the best implementation but it is a good representation of an auto-updating state machine.

class Program
    {
        static void Main(string[] args)
        {
            int[,] state = GetInputArray();
 
            for (int i = 0; i < 5; i++)
            {
                state = NexStep(state, i, (int)Math.Sqrt((double)state.LongLength));
                Console.WriteLine("**************************************************");
            }
 
            Console.ReadLine();
        }
 
        private static int[,] GetInputArray()
        {
            //int[,] state = new int[3, 3];
            //state[0, 0] = 0;
            //state[0, 1] = 1;
            //state[0, 2] = 0;
 
            //state[1, 0] = 0;
            //state[1, 1] = 1;
            //state[1, 2] = 0;
 
            //state[2, 0] = 0;
            //state[2, 1] = 1;
            //state[2, 2] = 0;
 
            int[,] state = new int[5, 5];
            state[0, 0] = 0;
            state[0, 1] = 1;
            state[0, 2] = 1;
            state[0, 3] = 1;
            state[0, 4] = 0;
 
            state[1, 0] = 0;
            state[1, 1] = 1;
            state[1, 2] = 0;
            state[1, 3] = 1;
            state[1, 4] = 0;
 
            state[2, 0] = 0;
            state[2, 1] = 1;
            state[2, 2] = 0;
            state[2, 3] = 1;
            state[2, 4] = 0;
 
            state[3, 0] = 0;
            state[3, 1] = 1;
            state[3, 2] = 1;
            state[3, 3] = 1;
            state[3, 4] = 0;
 
            state[4, 0] = 1;
            state[4, 1] = 1;
            state[4, 2] = 0;
            state[4, 3] = 1;
            state[4, 4] = 0;
            
            return state;
        }
 
        private static int[,] NexStep(int[,] state, int stepCounter, int arrSize)
        {
            int[,] newState= null;
 
            if (stepCounter > 0)
                newState = GetNextState(state,arrSize);
            else
                newState = state;
 
            PrintCurrentState(newState, arrSize);
 
            return newState;
        }
 
        private static void PrintCurrentState(int[,] state, int size)
        {
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    Console.Write(state[i, j]);
                    Console.Write(" ");
                }
 
                Console.Write(Environment.NewLine);
            }
        }
 
        static int[,] GetNextState(int[,] oldState, int arrSize)
        {
            int[,] newState = new int[arrSize, arrSize];
            for (int i = 0; i < arrSize; i++)
            {
                for (int j = 0; j < arrSize; j++)
                {
                    int aliveCells = GetAliveNeighbourCount(oldState, i, j, arrSize);
                    if (aliveCells < 2 || aliveCells > 3)
                        newState[i, j] = 0;
                    if (aliveCells == 2)
                        newState[i, j] = oldState[i, j];
                    if (aliveCells == 3)
                        newState[i, j] = 1;
                }
            }
 
            return newState;
        }
 
        static int GetAliveNeighbourCount(int[,] currState, int x, int y, int arrSize)
        {
            int sumOfCells = 0;
            for(int i = x - 1; i <= x + 1; i ++)
            {
                for (int j = y - 1; j <= y + 1; j++)
                {
                    if (i < 0 || j < 0) continue;
                    if (i >= arrSize || j >= arrSize) continue;
                    if (i == x && j == y) continue;
                    sumOfCells += currState[i, j];
                }
            }
 
            return sumOfCells;
        }
    }

Wednesday 21 November 2012

Performance issue in Excel Add-in with Range.Cells


Recently I worked on an interesting problem. My friend was developing an add-in for Excel 2010 and had a requirement to read content of each cell into a DataTable. Due to some restrictions with "named range" feature, he had to resort to reading value of each cell in a selected area. The code seemed alright but for some unexplained reason it was very slow.

The add-in used standard Visual Studio template for Office add-in projects and referenced Office Interop assemblies for performing operations on an excel file. The main code used a "for" loop through each cell and used Range.Cells[rowindex, columnindex].Value to read value from cell. 

The content in the selected range of sample file was also pretty small in size as it had 26 columns and 325 rows and each cell consisted of small string values e.g. "Test". Still, the add-in took about 18-20 seconds for reading the content.

After going through some results from web search, i came across this link in which it is suggested to assign Range.Value into a local variable and loop through that instead of looping through Range.Cells. After changing the code, the add-in was able to complete the operations in less than a second :). 

Lesson: Marshaling values between managed and unmanaged space is expensive and must be minimized. 

Calls to Range.Cells[i,j].Value are expensive and on an average took 2 milliseconds per call on my machine (dual core, 8 GB RAM) for the sample file. Below is a sample code i wrote to showcase the performance gain when Range.Values are used instead of Range.Cells[i,j].Value.

static void Main(string[] args)
        {
            var app = new Application();
            Workbook workbook = null;
            try
            {
                workbook = app.Workbooks.Open(@"D:\Excel.xlsx");
                Range rng = ((Worksheet)workbook.Sheets[1]).UsedRange;

                var arrValues = rng.Value;
                int maxrow = rng.Rows.Count;
                int maxcol = rng.Columns.Count;

                System.Data.DataTable dTable = new System.Data.DataTable("test");
                for (int i = 0; i < 26; i++)
                {
                    dTable.Columns.Add();
                }

                Stopwatch stopwatch = new Stopwatch();
                
                stopwatch.Start();
                ReadExcelIntoDataTable(arrValues, maxrow, maxcol, dTable);
                stopwatch.Stop();
                Console.WriteLine(stopwatch.ElapsedMilliseconds);

                long[] arr = new long[maxrow * maxcol];
                dTable.Clear();
                stopwatch.Restart();
                ReadExcelIntoDataTable2(rng, maxrow, maxcol, dTable, arr);
                stopwatch.Stop();
                Console.WriteLine(stopwatch.ElapsedMilliseconds);

                Console.WriteLine("Total cell read time : {0}", arr.Sum());
                Console.WriteLine("Average cell read time : {0}",arr.Average());
                Console.WriteLine("Min cell read time : {0}", arr.Min());
                Console.WriteLine("Max cell read time : {0}", arr.Max());

                Console.WriteLine("Total items : {0}", maxcol * maxrow);
            }
            finally
            {
                if (workbook != null)
                {
                    workbook.Close();
                    Marshal.ReleaseComObject(workbook);
                }

                if (app != null)
                {
                    Marshal.ReleaseComObject(app);
                }
            }

            Console.ReadLine();
        }
 private static void ReadExcelIntoDataTable(dynamic arrValues, int maxrow, int maxcol, System.Data.DataTable dTable)
        {
            DataRow dRow;
            for (int i = 2; i <= maxrow; i++)
            {
                dRow = dTable.NewRow();
                for (int j = 1; j <= maxcol; j++)
                {
                    dRow[j - 1] = arrValues[i, j];
                }
                dTable.Rows.Add(dRow);
            }
        }
 
        private static void ReadExcelIntoDataTable2(Range rng, int maxrow, int maxcol, System.Data.DataTable dTable, long[] arr)
        {
            int arrCounter = 0;
            DataRow dRow;
            Stopwatch stopwatch = new Stopwatch();
            for (int i = 2; i <= maxrow; i++)
            {
                dRow = dTable.NewRow();
                for (int j = 1; j <= maxcol; j++)
                {
                    stopwatch.Restart();
                    dRow[j - 1] = rng.Cells[i, j].Value;
                    stopwatch.Stop();
                    
                    arr[arrCounter] = stopwatch.ElapsedMilliseconds;
                    arrCounter++;
                }
                dTable.Rows.Add(dRow);
            }
        }

Below is the output of the program. Notice the reduction in execution time from 24+ seconds to 41 milliseconds :)

41
24150
Total cell read time : 19818
Average cell read time : 2.34532544378698
Min cell read time : 0
Max cell read time : 208
Total items : 8450


Monday 29 October 2012

Supported OS for .NET 4.5

Every time a new version of .NET framework is released, there is an associated cost :). Check out the list of supported client and server operating systems here. .NET 4.5 works on following OS:

1. Windows 8 (32 bit and 64 bit)
2. Windows 7 (32 bit and 64 bit)
3. Windows Vista SP2 (32 bit and 64 bit)
4. Windows Server 2012 (64 bit)
5. Windows Server 2008 R2 (64 bit)
6. Windows Server 2008 SP2 (64 bit)

So if you are planning to migrate your application to .NET 4.5, you might want to check the current state of hardware you possess. For example .NET 4.5 is not supported on Windows Server 2003.

Saturday 27 October 2012

Unit testing using Microsoft Fakes

Visual Studio 2012 has a very valuable feature called "Fakes" for the purpose of unit testing. Till now, our best bets were to use an Open Source or licensed third party solutions for mocking an object (interface or class) e.g. Moq, RhinoMock. Pex and Moles are also great solutions for mocking and test data generation using code analysis but they can not be used in commercial solutions. But with Visual Studio 2012, most of those features are built in.
Here is a simple example - Imagine a simple application which has a interface based implementation of business logic component and data access component : IBusinessComponent, IDataComponent are the interfaces and BusinessComponent and DataComponent implement the interfaces respectively. 


public interface IBusinessComponent
    {
        Customer GetCustomer(int customerId);

        Customer CreateCustomer(Customer customer);

        Customer UpdateCustomer(Customer customer);

        bool DeleteCustomer(int customerId);
    }


public interface IDataComponent
    {
        Customer GetCustomer(int customerId);

        Customer CreateCustomer(Customer customer);

        Customer UpdateCustomer(Customer customer);

        bool DeleteCustomer(int customerId);
    }

public class BusinessComponent : IBusinessComponent
    {
        private IDataComponent dataComponent;

        public BusinessComponent(IDataComponent dc)
        {
            this.dataComponent = dc;
        }

        public Customer GetCustomer(int customerId)
        {
            return this.dataComponent.GetCustomer(customerId);
        }

        public Customer CreateCustomer(Customer customer)
        {
            return this.dataComponent.CreateCustomer(customer);
        }

        public Customer UpdateCustomer(Customer customer)
        {
            return this.dataComponent.UpdateCustomer(customer);
        }

        public bool DeleteCustomer(int customerId)
        {
            return this.dataComponent.DeleteCustomer(customerId);
        }
    }


 public class DataComponent : IDataComponent
    {
...

public Customer GetCustomer(int customerId)
        {
            return customers.Where(c => c.Id == customerId).FirstOrDefault();
        }
...
}

We can simply add a unit test project to the solution and add reference of the 





project that has the core logic. Generating a "Fake" assembly is as straightforward as right clicking on the newly added reference and selecting "Add Fake Assembly" option. This adds fakes for the types present in the assembly. Now i can add mock of data component and write unit test that tests implementation in business component.

[TestMethod]
        public void GetCustomerTest()
        {
            FakesTesting.Interfaces.IDataComponent dataComponent = new FakesTesting.Interfaces.Fakes.StubIDataComponent()
                {
                    GetCustomerInt32 = (customerId) => { return new Customer() { Id = customerId }; }
                };
            FakesTesting.Interfaces.IBusinessComponent businessComponet = new FakesTesting.BusinessComponent(dataComponent);
            Customer c = businessComponet.GetCustomer(5);
            Assert.IsNotNull(c);
        }

        [TestMethod]
        public void GetCustomerTest2()
        {
            FakesTesting.Interfaces.IDataComponent dataComponent = new FakesTesting.Interfaces.Fakes.StubIDataComponent()
            {
                InstanceBehavior = new CustomStubBehaviorForDataComponent(),
                InstanceObserver = new CustomStubObserverForDataComponent(),
            };

            FakesTesting.Interfaces.IBusinessComponent businessComponet = new FakesTesting.BusinessComponent(dataComponent);
            Customer c = businessComponet.GetCustomer(5);
            Assert.IsNull(c);
        }
public class CustomStubBehaviorForDataComponent : IStubBehavior
{

 public TResult Result(TStub target, string name) where TStub : IStub
        {
            return default(TResult);
        }

        public bool TryGetValue(object name, out TValue value)
        {
            value = default(TValue);
            return true;
        }

        public void ValueAtEnterAndReturn(TStub target, string name, ref TValue value) where TStub : IStub
        {
            
        }

        public void ValueAtReturn(TStub target, string name, out TValue value) where TStub : IStub
        {
            value = default(TValue);
        }

        public void VoidResult(TStub target, string name) where TStub : IStub
        {
            
        }

}

public class CustomStubObserverForDataComponent : IStubObserver
    {
        public void Enter(Type stubbedType, Delegate stubCall, params object[] args)
        {
           
        }

        public void Enter(Type stubbedType, Delegate stubCall, object arg1, object arg2, object arg3)
        {
            
        }

        public void Enter(Type stubbedType, Delegate stubCall, object arg1, object arg2)
        {
            
        }

        public void Enter(Type stubbedType, Delegate stubCall, object arg1)
        {
            
        }

        public void Enter(Type stubbedType, Delegate stubCall)
        {

        }
    }



You can use any of the 2 approaches - 1. standard implementation redirection for method(s) 2. Finer mock behavior using custom implementations of IStubBehavior and IStubObserver interfaces.

Good thing about this framework is that you can generate stubs (mocking an interface's or class's implementation) and shims (mocking an implementation that you can not change e.g. System.DateTime) for assemblies that were compiled against older versions of .NET framework.