First released in 2016 by Microsoft, ASP.Net Core is an open-source, cross-platform re-design of the ASP.Net web-development framework. The idea behind ASP.Net and its successor was to provide programmers with a server-side framework to build dynamic web pages, apps, and services. ASP.Net Core is a part of the Microsoft .Net platform, combining several tools, programming languages, and libraries for developing various applications.
At Scalo, we utilize the .Net platform to provide comprehensive net development services, so we know a thing or two about improving the performance of ASP.Net-based apps. In the following article, we aim to share some of the expertise we have gained over the years.
Introduction to ASP.Net Core Performance
Since its inception, ASP.Net Core has been primarily focused on providing unparalleled performance in terms of speed and resource usage. And it does deliver on the promise, even giving the lightning-quick Node.js framework a run for its money, particularly in CPU-intensive tasks. Nevertheless, to get the most out of apps created with ASP.Net Core, developers need to follow certain practices and strategies. When utilized correctly, these actions can significantly improve the performance of the apps, making the ASP.Net Core an undoubted leader of the pack when it comes to the most popular web development frameworks. But, before we get to these optimization techniques, we first need to determine how the performance can be measured and compared.
Key Metrics to Measure ASP.Net Core Performance
Let’s begin by stating the obvious – performance is not only about speed. Your ASP.Net Core app can run blazingly fast but receive zero traffic. Your page can throw an exception whenever it is loaded or behaves erratically, e.g., not registering specific user actions. There are several ways to evaluate and monitor your ASP.Net Core-based app’s performance:
- Overall application performance – encompassing the most common metrics, such as average response time, error percentage, server CPU usage, requests per minute, etc.
- Key transactions/specific requests handling – some types of web requests are more important than others (e.g., shopping carts), and their performance can be a great indicator of the app’s overall condition.
- SQL queries – web apps that are heavily dependent on centralized SQL databases can suffer from significant performance issues. Monitoring the quality and volume of SQL queries is a must when the .Net Core app’s performance is at stake.
- App exceptions – when software underperforms, the first thing net developers usually look for are application errors. An increased number of certain exception types occurring clearly points to where the culprit may be hiding.
The list above can be extended even further depending on the application type. In certain scenarios, garbage collection optimization, specific app dependencies, or external web services’ performance can also be considered a viable source of data utilized to evaluate the ASP.Net Core app performance.
Tools for Monitoring and Testing ASP.Net Core Performance
One of the most significant advantages of the .Net platform is that it comes with a plethora of performance profiling tools. This number gets even bigger when we consider third-party app diagnostic tools. The .Net Core performance metric tools come in different shapes and forms, e.g.:
- EventCounters and System.Diagnostics.Metrics APIs
- Windows Performance Counters
- .Net code profilers
- ASP.Net Performance Profilers
- Application Performance Management (APM) tools
- Web Server Access Logs
- ASP.Net Failed Request Tracing tools
- Exception Tracking tools
It is worth noting that even though some of the tools above contain overlapping functionalities, each can be utilized to address different types of ASP.Net Core performance issues.
Best Practices for ASP.Net Core Performance Optimization
Now that we know how to measure the ASP.Net Core apps’ performance, it is time to determine what we can do to get the desired results. Some of the tips we share here are straightforward and quick to apply. Others require more in-depth knowledge, so if you are unsure about specific .Net best practices, get in touch with a software development company like ours and discuss your app’s performance improvements with the experts.
1. Configuring and Tuning Kestrel
Kestrel is a cross-platform web server included by default in ASP.Net Core project templates. It supports HTTPS, HTTP/2, Opaque upgrade for WebSockets, and Unix sockets. Kestrel’s configuration is one of the most vital factors affecting the performance of .Net Core projects, so getting it right is crucial. Unfortunately, there is no one-config-fits-all solution, as different requirements require different approaches. Please also note that the standalone Kestrel server cannot handle certain features like response caching, Request Filtering, external SSL certificates, or Windows Authentication. A lack of these features can have an adverse impact on the app’s performance, so integrating a reverse proxy server (e.g., IIS) within Kestrel’s configuration is recommended.
2. Caching and Content Delivery Networks
Caching (especially caching large objects) is one of the most common methods to achieve better performance in web applications. It reduces the number of requests to the server and database, which can drastically improve performance and reduce the site’s response times. This particular .Net framework supports response caching middleware that allows servers to optimize frequently-called code paths, store responses, and serve them via cache-related headers in HTTP response objects.
ASP.Net Core websites can also benefit from using Content Delivery Network (CDN), especially when they get a lot of international traffic. CDN consists of data centers worldwide, so the users accessing the website will connect to the server closest to them, resulting in much faster response times and less strain on the main hosting server.
3. Implementing Asynchronous Programming
Using asynchronous programming allows for the parallel execution of the code while accessing data from an API and performing I/O operations or independent calling. Allowing your application to handle many requests simultaneously can prevent Thread Pool starvation and help to avoid blocking calls. This will enable you to optimize data access logic, thus improving performance. Switching to asynchronous programming requires using asynchronous variants of regular commands (e.g., ToListAsync() instead of the synchronous ToList() method), so it may take a bit of getting used to it. But the result is definitely worth the effort.
4. Applying Response Compression and Optimizing Serialization
Typically, the server responses come as they are, in their original sizes. The response compression method, when applied correctly, can significantly reduce the amount of data sent over to the client, thus improving performance of the .Net Core applications. Conveniently, in ASP.Net Core, response compression was made available as a middleware component. Please note, though, that you should not compress files smaller than 1000 bytes or natively compressed assets, e.g., already optimized PNG or JPEG images.
While we’re on the topic of server responses, we shouldn’t forget JSON serialization. ASP.Net Core allows developers to use System.Text.Json for JSON serialization and deserialization from options. You can read and write JSON asynchronously without waiting for other processes to execute.
There are several ways to optimize the serialization process to improve performance. For example, you can instruct the run-time serializers to ignore specific fields within your class, effectively reducing the serialized data size.
5. Minimizing Database Round Trips
Data access is often the most resource-consuming process in an application, and minimizing database round trips is one of the most efficient methods used to increase the responsiveness of the software. The best way to reduce the number of requests is to combine as many actions as possible into a single query. The app will have to contact the server anyway, but from a performance standpoint, it’s always a good idea to keep the number of network round trips to a minimum.
6. Enabling Compression and Reducing HTTP Requests
It would be best if you compressed everything whenever possible. You will instantly notice a considerable performance boost once you enable compression and reduce the size of multiple files on the server. Minify your JavaScript files, use smart compression for images (don’t overdo it, though), and try to bundle all related files into one. This will also help you reduce the number of HTTP requests, which is often one of the main culprits of sub-par web app performance.
Common Performance Issues and How to Address Them
Sometimes, a massive performance improvement can be accomplished with a simple change to a single line of code. However, finding this line can be challenging. That is why we have listed some of the most common performance issues to help you with the search:
- Blocking calls – the .Net Core app often blocks the calls that can be asynchronous. You can avoid blocking calls by not using the Task.Wait method and Task<TResult>.Result property. ASP.Net Core apps perform best when set to run code in parallel.
- Garbage collection – allocating a sizable number of large objects in hot code paths can result in inconsistent performance or even running out of virtual memory. To avoid the risk of an OutOfMemoryException, you should think about caching these objects, especially the frequently used ones. Consider using ArrayPool<T> for storing large arrays.
- Exceptions – one should never utilize exceptions to control the normal program flow. Throwing and catching exceptions is relatively slow compared to other code flow patterns, especially in hot code paths. Your app should contain logic to identify and handle conditions prone to exceptions. Unusual or unexpected conditions should be the only viable reason for the .Net core application to throw or catch exceptions.
Conclusion and Future Considerations
The ASP.Net Core framework is a fantastic solution for building high-performance web apps and services. But to get the most out of it (or any other programming tool, for that matter), an intelligent approach backed by practical experience is needed. Incorporating the practices listed above into your development process will help you unlock the real potential of your web application. But if you think your project could use the assistance of seasoned professionals, why not get in touch with Scalo? Our teams of net development and back-end development experts will ensure that your ASP.Net Core application’s performance is nothing short of excellent.