Ways To Optimize Performance In ASP.NET Core Applications

Introduction

Distributed cache plays a major role in optimizing the application's performance by caching the data in memory and reducing database trips. In simple words, caching refers to storing the result of an operation so that the future request returns faster. 

When do we cache? 

  1. When the computation is slow. 
  2. Computation will run multiple times. 
  3. When the output is the same for a particular input, we know we don't have to recompute it every time because it will be the same result. 
  4. When your hosting provider charges for DB access. In this case, you can cache the response and reduce the unnecessary server hits, by this way, you can save some money. For example, the Google APP engine gives you a fixed number of reads and writes to the data store on a particular day, and if you go over that, you have to pay for it, even if the website doesn't get a lot of traffic.  

There are many ways to optimize performance in ASP.NET Core applications with NCache,

  1. Response Caching 
  2. Distributed Caching 
  3. Session Caching 
  4. Object Caching 
  5. SignalR

What is NCache?

NCache is an in-memory distributed cache for .NET, Java, and Node.js, and it is also open-source. NCache is super-fast and scalable and caches application data to reduce database trips. NCache is used to overcome the performance issues related to data storage, databases, and scaling the .NET, Java, and Node.js applications.

Get started with NCache, please go through the installation process of NCache. 

Response Caching

Response caching will cache the server responses for a request so that the subsequent request can access the data from the cache instead of hitting a server. For example, assume we have a country and state cascading  dropdown list  in our web form, so based on the country selected, the request will pass to the server, and we use it to get a respective state list,

In this case, the country and state data will never change frequently, so it is unnecessary to make country and state requests to the server whenever the web form loads; initially, we can save the response in the cache and for the consecutive calls instead of hitting the server we can get a saved response from a cache. We can cache any response from the HTTP request; it can be XML, Text, JSON, or HTML. We will get complete control over cached response using the cache-control property; for example, if cache-control: max-age=45 implies that the server response is valid for 45 seconds. 

There are different ways to cache the response. 

  1. In-memory 
  2. Response cache via HTTP Header 
  3. Distributed Caching 

1. In-Memory

In this approach, the response content will be cached in-memory on the server side and served for all subsequent calls. We can use built-in <cache> tags to define the section of the views to be cached.
Since the content is cached in-memory, it will be cleared on the application restarts. 

2. Response cache via HTTP Header

This approach caches the response content on the browser's end. It can reduce the server hits because the browser cache serves the subsequent calls.

3. Distributed Caching

In this approach, the response cache is distributed across several servers in a web farm that is external to an application. For subsequent calls, any server can be responded to. NCache provides a powerful distributed cache service to implement this approach, improving the application's performance by reducing server hits. 

NCache as a response caching middleware

NCache is one of the best response caching middleware for .NET web applications, providing the following benefits as a distributed cache. 

  1. 100% .NET- It is one of the distributed caches in the market, which is entirely built with .NET. 
  2. Fast and Scalable- It is very fast since it uses an in-memory distributed cache. We can scale it linearly, so NCache will be a great choice when we experience performance challenges in our ASP.NET Core application during high traffic. 
  3. High Availability- It supports peer clustering architecture, so there is no data loss when the cache server is down. 

Read more about NCache features here

Distributed Caching 

Distributed Caching is used to overcome the drawbacks of in-memory caching mechanisms regarding reliability and scalability. It will improve the application's performance when cloud services host the app. In the distributed cache, the cache is shared by multiple app servers and maintained as an external service. 

It has several advantages,

  1. It doesn't use local memory 
  2. Reliability -The cached data is available in the different data center 
  3. It's consistency across requests to multiple servers 

By default, ASP.NET Core has a distributed caching mechanism that persists the data in memory. The main drawback is the memory limit; the cached data will be cleared during the server restarts. Another approach is using the SQL Server, which has a drawback in performance; it will impact the application's performance when the load is high. So, the best approach is distributed caching with NCache. NCache is one of the distributed caching service providers. Using NCache, we can configure the ASP.NET Core application locally and in Azure as a distributed cache cluster. 

The AddNCacheDistributedCache extension method configures NCache as a provider for Distributed Caching for the ASP.NET Core web application. 

Download the NuGet package and add the below code to the program.cs file.

builder.Services.AddNCacheDistributedCache(configuration => {
    configuration.CacheName = "democache";
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
});

If there is any update in the record from the database, it will cache the new data.

Session Storage in ASP.NET Core using NCache 

HTTP is a stateless protocol, which means the information will not persist across multiple requests; we need to use a session storage mechanism for the ASP.NET Core application to persist the information across multiple requests. By default, ASP.NET Core will use in-memory storage to store the session information, this is fine to some extend, but whenever there is high traffic, this session storage may fail due to some limitations. 

Memory Limitation

Since the session information is directly stored in-memory, memory space might be a major concern here; if the memory space exceeds more than the limitation, the session storage will fail.

Session Loss

If the application server goes down, the session loss occurs. 

ASP.NET Core provides two options to perform session caching,

  1. Session storage provider and  
  2. IDistributedCache interface 

Both of them are fast in managing the session information; however, both are stand-alone caches with a single point of failure and no option for data replication when the server goes down. 
So, the perfect solution to overcome this issue is storing the session information in distributed session storage. NCache is an in-memory distributed Cache provider developed natively in .NET and .NET Core; it's fast and scalable.

Configuring the NCache on the default Sessions Storage provider and IDistributed Cache interface is simple. Know more about session caching in NCache here.

Advantages of using NCache

1. Data replication capability

NCache provides data replication capability so that the session information will be available in the different centers for different regions; if any region went down, it would reroute the traffic from one region to another. 

2. It also offers session sharing between separate cache clusters. 

Configuring NCache as a Session Storage Provider

1. Install the following NuGet Package Manager 

a.    For Open source
Install-Package AspNetCore.Session.NCache.OpenSource

b.    For Professional 
Install-Package AspNetCore.Session.NCache.Professional 

c.    For Enterprise 
Install-Package AspNetCore.Session.NCache

2. Configure the session using the AddNCacheSession extension method, and add the below code to the program.cs file. 

builder.Services.AddNCacheSession(configuration => {
    configuration.CacheName = "[your clustered cache name]";
    configuration.EnableLogs = true;
    configuration.SessionAppId = "demoAppSession";
    configuration.SessionOptions.IdleTimeout = 5;
    configuration.SessionOptions.CookieName = "AspNetCore.Session";
});

3. Configure the NCache settings in appsettings.cs file 

{
  "NCacheSettings": {
    "SessionAppId": "demoAppSession",
    "SessionOptions": {
      "CookieName": "AspNetCore.Session",
      "CookieDomain": null,
      "CookiePath": "/",
      "CookieHttpOnly": "True",
      "IdleTimeout": "5",
      "CookieSecure": "None",
     "useJsonSerialization": true,
    },

    "CacheName": "demoClusteredCache",
    "EnableLogs": "True",
    "RequestTimeout": "90"
  },
}

Reference: ASP.NET Core Session Provider Configuration | NCache Docs (alachisoft.com) 

Object Caching 

Object Caching is one of the techniques to cache the object data to improve the ASP.NET Core application performance. 

 Assume we have an ASP.NET Core Web API service that returns a list of available countries in the world; in this case, whenever there is a request from the client, the service will fetch the country list from the database and return it to the client. In this case, we know the Country object data will not be frequently updated. So, caching this object in a distributed cache will avoid unnecessary database trips and improve the application's performance. 

NCache provides two APIs to achieve object caching,

  1. NCache API 
  2. IDistributedCache API

1. NCache API 

NCache API has an extension method GetCache which is used to connect to an instance of the NCache within the application. 

Learn about the configuration here

2. IDistributedCache API

If your application already uses the default distributed cache, the IDistributedCache API of NCache can be easily configured on top of the default one. 

We already discussed IDistributedCache in the above DistributedCache section. 

Learn about the configuration here

SignalR

What is ASP.NET Core SignalR? 

SignalR is used to fetch the content from the server side to clients instantly and manages the connection seamlessly. It is an open-source Microsoft API. It uses remove procedure call shortened to RPC to call the client from the server. Hubs establish a core connection between the server and the client, and it will have complete control over the connections.  

Use cases for SignalR,

  • Real-time monitoring applications
  • Chat application 
  • Scoreboard application 
  • IoT Device control and so on.  

SignalR Backplane

It is a shared bus or repository. We can configure a Webfarm as a backplane so that instead of sending a message from a web server to the clients, the backplane can be broadcast to all the web servers with all the servers connected to the backplane. 

Main bottlenecks with SignalR Backplane,

  • Database as SignalR Backplane is slow; it cannot scale out with increasing applied load. 
  • The database can slow down under high load, which may led to single-point failure sometime. 

Integrating a scalable NCache In-memory Distributed Cache to our ASP.NET Core SignalR application can overcome all these bottlenecks and improve performance. 

Configuring NCache as a backplane for ASP.NET Core SignalR application,

1. Download and install the NCache Nuget Package

dotnet add package AspNetCore.SignalR.NCache --version 5.3.1

2. Configure NCache settings in appsettings.json 

"NCacheConfiguration": {
  "CacheName": "myLocalCache",
  "ApplicationID": "chatApplication"
},

3. Using the AddNCache extension method, we can easily configure our application and add the below code in the program.cs. 

builder.Services.AddSignalR().AddNCache(ncacheOptions => {
    ncacheOptions.CacheName = Configuration["NCacheConfiguration:CacheName"];
    ncacheOptions.ApplicationID = Configuration["NCacheConfiguration:ApplicationID"];
});

Learn more-  Get Started With NCache Backplane For .NET Core SignalR (c-sharpcorner.com) 

Summary

We have seen a different technique for improving the performance of the ASP.NET Core applications using response cache, distributed cache, SignalR cache, and session and object cache with NCache. We also saw the overview of response, distributed, SignalR, session, and object cache on what, why, and the advantages of using this caching mechanism with NCache, which is super-fast and linearly scalable, and it is built on .NET to overcome the performance bottleneck in our ASP.NET Core web applications.