Imagen de Maitree Rimthong en Pexel

Lo primero es recomendarte leer este artículo para que veas la relación entre ambos:

https://jmfloreszazo.com/httpclient-vs-ihttpclientfactory/

Cuando tengas contexto con el anterior artículo continua leyendo este.

En el ecosistema de .NET 8, dos de las herramientas más esenciales para manejar peticiones HTTP son HttpClient y HttpFactory. A primera vista, podría parecer que comparar estas dos entidades es como comparar manzanas con naranjas. Algunos dirán que cada una tiene su propósito y contexto de uso bien definido, y no cabe la comparación. Otros, en cambio, podrían sentir curiosidad por las sutilezas que las diferencian y cómo estas pueden impactar el desarrollo de aplicaciones robustas y eficientes.

Confieso que me asaltó la duda: ¿tiene sentido establecer un paralelo entre HttpClient y HttpFactory? ¿O estamos hablando de dos conceptos tan distintos que la comparación es innecesaria, incluso forzada? Guiado por esta inquietud, he decidido emprender un experimento que, espero, arroje luz sobre sus comportamientos y nos ayude a comprender mejor cuándo y cómo utilizar cada uno.

Gracias a BenchmarkDotNet vamos a salir de dudas.

Ejemplo:

HttpClientFactoryBenchmark.cs

using BenchmarkDotNet.Attributes;
using Microsoft.Extensions.DependencyInjection;

namespace httpclientfactorybenchmark;

public class HttpClientFactoryBenchmark
{
    private IHttpClientFactory _httpClientFactory;
    private HttpClient _httpClientfromHttpClient;
    private HttpClient _httpClientfromHttpFactory;

    [GlobalSetup]
    public void GlobalSetup()
    {
        var services = new ServiceCollection();
        services.AddHttpClient();
        var serviceProvider = services.BuildServiceProvider();
        _httpClientFactory = serviceProvider.GetRequiredService<IHttpClientFactory>();
        _httpClientfromHttpClient = new HttpClient();
        _httpClientfromHttpFactory = _httpClientFactory.CreateClient();
    }

    [Benchmark]
    public async Task TestWithHttpClientFromConstructor()
    {
        var response = await _httpClientfromHttpClient.GetAsync("https://jsonplaceholder.typicode.com/todos");
        response.EnsureSuccessStatusCode();
    }

    [Benchmark]
    public async Task TestWithHttpFactoryFromConstructor()
    {
        var response = await _httpClientfromHttpFactory.GetAsync("https://jsonplaceholder.typicode.com/todos");
        response.EnsureSuccessStatusCode();
    }

    [Benchmark]
    public async Task TestWithHttpClientFromCreation()
    {
        using var httpClient = new HttpClient();
        var response = await httpClient.GetAsync("https://jsonplaceholder.typicode.com/todos");
        response.EnsureSuccessStatusCode();
    }

    [Benchmark]
    public async Task TestWithHttpFactoryFromCreation()
    {
        using var httpClient = _httpClientFactory.CreateClient();
        var response = await httpClient.GetAsync("https://jsonplaceholder.typicode.com/todos");
        response.EnsureSuccessStatusCode();
    }
}

Program.cs

using BenchmarkDotNet.Running;
using httpclientfactorybenchmark;

//dotnet run -c Release -f net8.0 --project httpclientfactorybenchmark

BenchmarkRunner.Run<HttpClientFactoryBenchmark>();
Ejecutamos

Y podremos observar, como se comporta instanciando en el constructor y en cada método.

Conclusión:

Pues algo tan sencillo como que si solo necesitas un HttpClient (con sus pros y contras, leer anterior artículo), logicamente estas ganando tiempo 3ms, en una instancia de un singleton (habitualmente).

Pero donde se ve claramente como la factoria recicla los HttpClient y hace un uso gestionado por el propio .NET8 es en la segunda parte del ejercicio.

Para mi lo importante es que se muestra como funciona el reciclado ya que más jugo no se le puede sacar a la comparativa y que si quires añadir unos ms a tus aplicaciones de alta demanda, quizá tengas que discutirle a quien toque si es obligatorio tener la potencia que da la factoria o no, o bien decir que la factoria te quita un prosible problema que por 3ms bien vale tardar un instante más en inicalizar.

Lo que me gusta de estas mediciones es que te da argumentos para poner tus decisiones en valor y respaldadas con datos reales.

Espero que este pequeño ejercicio te ayude a comprender mejor el artículo inicial y que puedas apreciar la potencia de hacer benchmark.