itsdrea
itsdrea

Reputation: 11

C# Slow response times with HttpClient compared to HttpWebRequest

For some reason when doing the same POST request with HttpClient and HttpWebRequest, HTTPClient takes 2000+ms while HttpWebRequest takes around 1000-1400 ms. Is this disparity normal and is there anything I can do to make the httpclient match the speed of the httpwebrequest?

I've posted code below in case I'm messing something up.

protected WebRequest CreateWebRequest(Uri uri)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(EndPoint));
    request.Method = "POST";
    request.ContentType = "application/json-rpc";
    request.Headers.Add(HttpRequestHeader.AcceptCharset, "ISO-8859-1,utf-8");
    request.Headers.Add(CustomHeaders);
    request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
    request.ServicePoint.Expect100Continue = false;
    ServicePointManager.Expect100Continue = false;
    return request;
}

private async Task<string> DoHttpClientPost(string method, IDictionary<string, object> args = null)
{
    {
        HttpClientHandler handler = new HttpClientHandler()
        {
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        };
        handler.Proxy = null;
        HttpResponseMessage response;
        using (var myHttpClient = new HttpClient(handler))
        {
            myHttpClient.DefaultRequestHeaders.ExpectContinue = false;
            myHttpClient.DefaultRequestHeaders.Add("Accept-Charset", "ISO-8859-1,utf-8");
            myHttpClient.DefaultRequestHeaders.Add(APPKEY_HEADER, CustomHeaders.GetValues(APPKEY_HEADER));
            myHttpClient.DefaultRequestHeaders.Add(SESSION_TOKEN_HEADER, CustomHeaders.GetValues(SESSION_TOKEN_HEADER));
            myHttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json-rpc"));
            var call = new JsonRequest { Method = method, Id = 1, Params = args };
            var jsonObject = JsonConvert.Serialize<JsonRequest>(call);
            var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json-rpc");
            response = await myHttpClient.PostAsync(new Uri(EndPoint), content);
        }
        Console.WriteLine("\nCalling: " + method + " With args: " + JsonConvert.Serialize<IDictionary<string, object>>(args));
        string jsonResponse = await response.Content.ReadAsStringAsync();

        return jsonResponse;
    }
}


public async Task<T> Invoke2<T>(string method, IDictionary<string, object> args = null)
{
    if (method == null)
        throw new ArgumentNullException("method");
    if (method.Length == 0)
        throw new ArgumentException(null, "method");
    string jsonString = await DoHttpClientPost(method, args);
    var jsonResult = JsonConvert.Deserialize<JsonResponse<T>>(jsonString);

    return jsonResult.Result;
}



public async Task<T> Invoke<T>(string method, IDictionary<string, object> args = null)
{
    if (method == null)
        throw new ArgumentNullException("method");
    if (method.Length == 0)
        throw new ArgumentException(null, "method");

    var request = CreateWebRequest(new Uri(EndPoint));

    using (Stream stream = request.GetRequestStream())
    using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
    {
        var call = new JsonRequest { Method = method, Id = 1, Params = args };
        JsonConvert.Export(call, writer);
    }
    Console.WriteLine("\nCalling: " + method + " With args: " + JsonConvert.Serialize<IDictionary<string, object>>(args));

    using (WebResponse response = GetWebResponse(request))
    using (Stream stream = response.GetResponseStream())
    using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
    {
        var jsonResponse = JsonConvert.Import<T>(reader);
        // Console.WriteLine("\nGot Response: " + JsonConvert.Serialize<JsonResponse<T>>(jsonResponse));
        if (jsonResponse.HasError)
        {
            throw ReconstituteException(jsonResponse.Error);
        }
        else
        {
            return jsonResponse.Result;
        }
    }
}

Upvotes: 0

Views: 2887

Answers (1)

Slokken
Slokken

Reputation: 31

HttpClient should, if possible, be reused across requests. Have you tried isolating creating the HttpClient instance, and performing the actual request? Both creating and disposing the resources held by the instance does take time, although 1000ms sounds like a lot.

Another possible cause of slowdowns when using HttpClient or WebRequest is setting ServicePointManager.DefaultConnectionLimit too low. The default is 2, so if you're doing a lot of concurrent or even several requests in fast succession, you'll end up waiting for the ServicePointManager to free the connections.

Upvotes: 3

Related Questions