Executando verificação de segurança...
2

Primeiramente parabéns, é muito bom ver novos projetos da comunidade .NET. Acredito que serve muito bem ao propósito de ser simples e não obrigar as convenções do framework.

Não pude deixar de testar, notei que é levemente mais lento do que as MinimalApis, acreditei que por ser mais enxuto, seria mais rápido.

|     Method |     Mean |   Error |  StdDev |   Median |
|----------- |---------:|--------:|--------:|---------:|
| MinimalApi | 135.3 us | 2.68 us | 4.40 us | 134.1 us |
|    SiskApi | 193.0 us | 3.84 us | 8.51 us | 189.5 us |

Esse é minha codificação de API:

private static async Task MinimalApi()
{
    var app = WebApplication.CreateBuilder().Build();
    app.MapGet("/", () => new string('*', 10));
    await app.RunAsync();
}

Poderia ser algo que implementei a mais na configuração do Sisk?

private static async Task SiskApi()
{
    var http = HttpServer.Emit(insecureHttpPort: 5222, out _, out _, out var mainRouter);
    mainRouter += new Sisk.Core.Routing.Route(RouteMethod.Get, "/",
        request => new Sisk.Core.Http.HttpResponse(200) { Content = new StringContent(new string('*', 10)) });
    await Task.Run(http.Start);
}
Carregando publicação patrocinada...
1

Muito bacana você ter testado! Em breve quero criar benchmarks mais interessantes e deixar no site também.

Eu não sei exatamente como você realizou a medição, mas se usou a MinimalAPI do ASP.NET, tem uma diferença. O Sisk utiliza a interface do sistema operacional para abrir o servidor HTTP, então uma chamada nativa é feita para instanciar o servidor HTTP. Essa chamada é diferente para cada sistema operacional, e nisso acaba tendo uma ínfima latência para criar o objeto COM.

Nos últimos ASP.NET, estão usando o Kestrel, que é um servidor HTTP escrito em C#. O servidor já é compilado no próprio código, então fica mais rápida a abertura do mesmo.

Também não sei se o seu teste chamou a rota / que você criou em ambas funções. O que exatamente você mensurou? A criação do ambiente? Uma rota? Dê mais detalhes, ficarei feliz em participar.

1

O método foi bem simples, vou tentar deixar os detalhes aqui. Usei o pacote BenchmarkDotNet para realizar a medição e como você bem disse, apenas chamei a rota / de ambos os servidores configurados como mandei anteriormente, usei de fato kestrel para MinimalAPI, e basicamente envolvi o http.Start do servidor Sisk em um Task.Run() para que ambos rodassem e paralelo.

O start dos dois servidores foi dessa forma

Task.WaitAll(SiskApi(), MinimalApi());

E aqui está o código da medição.

public static class Program
{
    private static void Main() => BenchmarkRunner.Run<SiskVsMinimalBenckmark>();
}

public class SiskVsMinimalBenckmark
{
    private HttpClient? _httpClient;

    [GlobalSetup]
    public void Setup() => _httpClient = new HttpClient();

    [Benchmark]
    public async Task MinimalApi() => await _httpClient!.GetStringAsync("http://localhost:5221/");

    [Benchmark]
    public async Task SiskApi() => await _httpClient!.GetStringAsync("http://localhost:5222/");
}
1

Refiz os testes e consegui resultados um pouco melhores, mas ainda piores que o ASP.NET:

MethodMeanErrorStdDev
AspNetMinimal101.9 us1.13 us0.95 us
SiskDotNet108.4 us1.50 us1.40 us
SiskBFlat109.9 us1.58 us1.48 us

Também inclui um teste com o Sisk compilado com bflat. Achei que se sairia melhor porque não tinha toda aquela VM do .NET, mas acabou sendo pior.

Para melhorar os testes, eu desabilitei alguns switches de configuração do Sisk:

config.AccessLogsStream = null;  // o access logging pesa muito o processamento
config.Flags.NormalizeHeadersEncodings = false;
config.Flags.SendSiskHeader = false;
config.IncludeRequestIdHeader = false;

E também movi a resposta para um objeto, para não ter que computar o ByteArrayContent toda requisição. Não sei se é justo fazer isso, não sei como é no ASP.NET.

Acho que a diferença restantes dos 6,5 us é parte da implementação do soquete HTTP em si. Todas requisições foram feitas em HTTP plano, sem TLS. Aliás, o benchmark tá aqui se você quiser mais detalhes.

Fiquei feliz em ter aproximado o valor, fica mais competitivo.

1

Obrigado pelos detalhes!

Vou usar isso para diagnosticar a chamada de funções até entregar a resposta final e ver como posso otimizar ainda mais isso.