Monday, 18 November 2019

Benchmarking in DotNet to analyse memory footprint

BenchmarkDotNet is a performance measurement tools which generate various console data like
Avg execution time, memory allocation, memory distribution and more for executed methods.


  • It have features to export result in various format.
  • It works with release mode only.
  • Support with console App only, Doesn't support with unit test.
Official Documentation, Youtube Demo


Example:
Let's suppose that we want to explore performance of string replace for both String.Replace & Regex.Replace function. We have prepared dummy csv data by running a loop from 1 - 10000. And created 2 diff functions StringReplace() and RegexReplace() in class StringReplaceVsRegexReplaceBenchmark. We have added vital attributes which BenchmarkDotNet understand. We have chosen Release mode and pressed Ctrl + F5 (Start without debugging).

With given full code snippet, output could be found over console.

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System;
using System.Collections;
using System.Linq;
using System.Text.RegularExpressions;
 
namespace ReplaceVsRegex
{
    [MemoryDiagnoser]
    [RPlotExporterRankColumn]
    public class StringReplaceVsRegexReplaceBenchmark {
        
        private string data;
        
        [GlobalSetup]
        public void Setup()
        {
            data = string.Join(""Enumerable.Range(1, 10000));
        }
 
        [Benchmark]
        public void StringReplace() =>
            data.Replace("1""x");
 
        [Benchmark]
        public void RegexReplace() =>
            Regex.Replace( data, "1""x");
    }
 
    public class Program
    {
        public static void Main(string[] args)
        {
            var summary = BenchmarkRunner.Run<StringReplaceVsRegexReplaceBenchmark>();
        }
    }
}
  
Output:



Wednesday, 16 October 2019

GAC in .Net, step by step installation of library [Revision]

Reasons why we need to install an assembly into the global assembly cache:

  • Shared location: Various app can access through shared location.
  • File security: Administrator privileges required to manage GAC so no other can delete ii.
  • Side-by-side versioning: Multiple copies of assemblies with the same name but different version information can be maintained in the global assembly cache.


Let see how we can complete library installation in GAC easily.

1. If Visual Studio installed in system, find Developer Command Prompt and run as administrator.

2. Check gacutil command by listing all existing installed library by command line
gacutil -l



3. Search library by name using command line
gacutil -l <dll name>


4. Install dll by command line
gacutil -I <dll name along with full path>


5. Check again if newly added dll is available or not by using command
gacutil -l <dll name>


6. Delete/uninstall dll from GAC by using command
Gacgutil -u <dll name> 



Problems/Questions:
1. Failure adding assembly to the cache: Administrator permissions are needed to use the selected options. Use an administrator command prompt to complete these tasks.

Solution: Re run developer command prompt as administrator.


2. Failure adding assembly to the cache: Strong name signature could not be verified.  Was the assembly built delay-signed?

Solution: Make sure you have created a strong name for your library and Delay sign only is partially checked.





3. Can we have multiple library installed with same name in GAC?
Answer: Yes, Name will be same but version will be different.

4. Can we install netstandard2.0 dll in to GAC?
Answer: Yes



Friday, 11 October 2019

Task CancellationToken .net C# example, Solution for - how to kill long running task in C#?

Here we are exploring a small demo, of how cancellation token play a  big role in managing the long running task. Most of the time we use Task, Async, await to take the advantage of system thread to boost performance. But some time we ignore Task Cancellation to implement.




By exploring both  console application and web Api in Dotnet core, we will see how cancellation token affect the running task. You can get full running demo from GitHub demo.

So let's start with console application,

using System;
using System.Threading;
using System.Threading.Tasks;
 
namespace TaskCancellationByToken.ConsoleDemo
{
    class Program
    {
        public static Task PrintWithCancellationToken(int count, CancellationToken cancellationToken)
        {
            for (int i = 1; i <= count; i++)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }
                else
                {
                    Console.Write(nameof(PrintWithCancellationToken));
                    Console.WriteLine(i);
                }
                Thread.Sleep(10);
            }
 
            return Task.FromResult(0);
        }
        
        public static Task Print(int count)
        {
 
            for (int i = 1; i <= count; i++)
            {
                Console.Write(nameof(Print));
                Console.WriteLine(i);
                Thread.Sleep(10);
            }
            return Task.FromResult(0);
 
        }
 
        static void Main(string[] args)
        {
            Parallel.Invoke(async () =>
                await Print(500),
                async () =>
                {
                    using (CancellationTokenSource cTokenSource = new CancellationTokenSource())
                    {
                        var keyBoardTask = Task.Run(() =>
                        {
                            Console.WriteLine("Press enter to cancel");
                            Console.ReadKey();
 
                            // Cancel the task
                            cTokenSource.Cancel();
                        });
 
                        await PrintWithCancellationToken(500, cTokenSource.Token);
                    }
                }
                );
            Console.WriteLine("Hello World!");
        }
    }
}

Here in console application

  • We have 2 methods that print Counting value from 1 to 500 along with method name.
  • Printing is happening with some sleep interval, so that task will take some time to execute.
  • We are running both the task parallel.
Now what we want that while we press enter one task should be stop in between, and so we used cancellation token.

Let's verify output here will see PrintWithCancellationToken stopped in between.





Now moving toward 2nd demo which is Dotnet core web Api.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
 
namespace TaskCancellationByToken.WebApiDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        [HttpGet("WithCancellationToken")]
        public ActionResult<IEnumerable<string>> Get(CancellationToken cancellationToken)
        {
            List<string> lst = new List<string>();
            for (int i = 1; i <= 10; i++)
            {
                //cancellationToken.ThrowIfCancellationRequested(); //System.OperationCanceledException: 'The operation was canceled.'
                if (cancellationToken.IsCancellationRequested)
                {
                    Debug.WriteLine("Task Cancled");
                    break;
                }
                else
                {
                    var value = "value" + i;
                    lst.Add(value);
                    Debug.WriteLine(value);
                }
                Thread.Sleep(1000);
            }
            Debug.WriteLine("Task Finished");
            return lst;
        }
 
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            List<string> lst = new List<string>();
            for (int i = 1; i <= 10; i++)
            {
                var value = "value" + i;
                lst.Add(value);
                Debug.WriteLine(value);
                Thread.Sleep(1000);
            }
            Debug.WriteLine("Task Finished");
            return lst;
        }
    }
}

Here in dotnet core web api,

  • We have 2 action for ValueController and like same console application we have 2 action here one use cancellation token and 2nd doesn't use cancellation token.
  • We will be verifying output in browser and output tab in visual studio for debug information.

If we verify normal action execution even if we stop or abort http request from browser entire execution process running till end.


 But if we have implemented Cancellation token for API and we cancel it from browser or from client, execution terminate in background as well.




Now you can evaluate how useful it is to implement Cancellation token with Task in web API.


Friday, 4 October 2019

Generate complex fake object in C#

Sometimes we need to create sample data to test our Api and so we create factory that provide us some data. Either we hard cord some static values or write some code to dynamically generate n-rows list. Here we will be exploring how to generate fake data for you C# Model by using third parties.

Two popular faker is Bogus and GenFu.

Bogus & GenFu both support much complex scenario that required some additional configuration. Writing configuration separately again not always suite for each requirement. Like:

My basic requirement is to simply generate fake simple and complex object or list of simple and complex fake object up-to n rows. I don't want to write much configuration code, just wanted to have some dummy data for my complex object with only implementation code.

Install-Package ComplexFaker


IFakeDataService faker = new FakeDataService();

            //Generate Simple obj
            var obj1 = faker.Generate<ChargeSummaryDto>();

            //Generate List of simple obj with default array length 2.
            var obj2 = faker.Generate<List<ChargeSummaryDto>>();

            //Generate Simple obj user defined array length 5.
            var obj3 = faker.Generate<List<ChargeSummaryDto>>(5);

            //Generate Complex list with default array length 2.
            var obj4 = faker.GenerateComplex<List<ChargeSummaryDto>>();

            //Generate Complex list with user defined array length 5.
            var obj5 = faker.GenerateComplex<List<ChargeSummaryDto>>(5);

Monday, 23 September 2019

CQRS basic implementation in DotNetCore

Command and Query Responsibility Segregation (CQRS) pattern  day by day gaining its popularity and recently found reference on Official Microsoft.

The words Command, Query, Responsibility and Segregation well define the CQRS.
Which says, We should segregate operations by using separate interface, which can maximize performance, scalability and security.

Benefits:

  • Independent scaling
  • Optimized data schemas.
  • Security
  • Separation of concerns
  • Simpler queries


Implementation of CQRS lead to more complex application design but it also suit best for the robust application design.


Let's have a look on simple design

Customer using
>------Client App using
>-----------Query to Get result,or
>-----------Command to Post and Patch etc to Add/Update data by using an
>-------------------------Web Api which have separate (DotnetCore webapi)
>---------------------------------------Validation layer (FluentValidation)
>----------------------------------------Command/Query handler to implement business logic MediatR)
<------------Send response back to client app


Above implementation could be found in GitHub Repo

Where we used

  • DotnetCore
  • EntityFrameworkCore
  • MsSql and InMemoryDatabase, As storage based on configuration.
  • FluentValidation, To implement model validation.
  • MediatR, To implement CQRS.
  • Automapper, To project object.


Wednesday, 18 September 2019

JsonPatchDocument in ASP.NET Core web API to use PATCH verb

Recently got chance to work with PATCH verb in DotNetCore, which allow us to update model partially. Nice reference could be found on Official Microsoft and Dotnetcoretutorials.

In short, we just need to understand PATCH Operations, make valid JSON patch request and correct implementation of JsonPatchDocument in dotnetcore action.

Operation details could be found here ,


And make call to endpoint with valid request, like in below request I just want to update the userName as Raj.

JSON Request:
[
  {
    "op": "replace",
    "path": "/userName",
    "value": "Raj"
  }
]


JsonPatchDocument Implementation in dotnet core API

/// <summary>
         /// Jsons the state of the patch with model.
         /// </summary>
         /// <param name="userId">The user identifier.</param>
         /// <param name="userPatch">The user patch.</param>
         /// <returns>Updated user</returns>
         [HttpPatch]
         public async Task<IActionResultPatchUserAsync(int userId, [FromBodyJsonPatchDocument<UserDtouserPatch)
         {
             if (userPatch != null)
             {
                 //Get existing user from DB through service or repository.
                 var user = await _userService.GetUserAsync(userId); 
                 //Apply patch to existing user.
                 userPatch.ApplyTo(user);
  
                 //Again validate model
                 if (!ModelState.IsValid)
                 {
                     return BadRequest(ModelState);
                 }
  
                 //Update user through service or repository.
                 await _userService.UpdateUserAsync(UserId, user);
  
                 //Return updated user.
                 return new ObjectResult(user);
             }
             else
             {
                 return BadRequest(ModelState);
             }
         }

Tuesday, 6 August 2019

Execute command and get cmd output in C#

Given below code snippet will help us to execute any command line in background and trace output.
For example, we want to know git status of current working directory.


//Console.WriteLine(CommandOutput("git status"));
 
public static string CommandOutput(string command,
                                   string workingDirectory = null)
{
    try
    {
        ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd""/c " + command);
 
        procStartInfo.RedirectStandardError = procStartInfo.RedirectStandardInput = procStartInfo.RedirectStandardOutput = true;
        procStartInfo.UseShellExecute = false;
        procStartInfo.CreateNoWindow = true;
        if (null != workingDirectory)
        {
            procStartInfo.WorkingDirectory = workingDirectory;
        }
 
        Process proc = new Process();
        proc.StartInfo = procStartInfo;
        proc.Start();
 
        StringBuilder sb = new StringBuilder();
        proc.OutputDataReceived += delegate (object sender, DataReceivedEventArgs e)
        {
            sb.AppendLine(e.Data);
        };
        proc.ErrorDataReceived += delegate (object sender, DataReceivedEventArgs e)
        {
            sb.AppendLine(e.Data);
        };
 
        proc.BeginOutputReadLine();
        proc.BeginErrorReadLine();
        proc.WaitForExit();
        return sb.ToString();
    }
    catch (Exception objException)
    {
        return $"Error in command: {command}{objException.Message}";
    }
}