HttpClient Performance Issues

 

As developers, we all have to write software at some point to talk to various RESTful APIs and end points, this usually involves using the HttpClient, WebRequest or WebClient. Each of these have their advantages and disadvantages depending on your requirements. HttpClient (System.Net.Http) was introduced in .NET 4.5 and provides the simplicity of WebClient whilst harnessing the power of WebRequest, which makes it a popular choice in newer developments.

It does have a nasty surprise for anyone using it without much experience (I still add myself to that category!). Essentially, it is an IDisposable object that should be instantiated once, and then shared as a single instance throughout the entire application’s life cycle. The reason for this is that if it isn’t, then this can quickly consume the available network sockets causing severe performance issues of the application. Particularly if the application is under heavy load.

Below are some useful examples on how you might structure your code to prevent unnecessary performance issues.

Bad Usage


// Using System.Net.Http
void Main()
{
	for(int i = 0; i < 5; i++)
	{
		using(HttpClient httpClient = new HttpClient())
		{
			var webResult = Client.GetAsync("http://www.google.com").Result;
			Console.WriteLine(webResult.StatusCode);
		}
	}
}

 

Best Usage


// Using System.Net.Http
private static HttpClient Client = new HttpClient();

void Main()
{
	for(int i = 0; i < 5; i++)
	{
		var webResult = Client.GetAsync("http://www.google.com").Result;
		Console.WriteLine(webResult.StatusCode);
	}
}

 

Multi-threaded Usage

Since HttpClient supports asynchronous requests, it does allow you to use the single instance for multi-threading as well, which is a useful feature.


// Using System.Threading
// Using System.Threading.Tasks
// Using System.Net.Http
private static HttpClient Client = new HttpClient();

async Task Main()
{
	// Declare the tasks first to prevent thread deadlocking/sequential running
	var firstTask = GetPageContentAsync("http://www.google.co.uk");
	var secondTask = GetPageContentAsync("http://www.lycos.co.uk");
	
	// Await the tasks to finish before carrying on
	string pageOne = await firstTask;
	string pageTwo = await secondTask;
}

public async Task GetPageContentAsync(string uri)
{
	string pageContent = null;
	var response = await Client.GetAsync(uri);

	if(response.IsSuccessStatusCode) // Safe to return results?
	{
		pageContent = await response.Content.ReadAsStringAsync();
	}
	
	return pageContent;
}

 

Post Categories