解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
3.23 KiB
X
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using BenchmarkDotNet.Attributes;
using NewLife;
using NewLife.Http;

namespace Benchmark.StreamingBenchmarks;

/// <summary>HTTP 流式响应基准:BodyStream 流式发送 vs 整段物化响应(回环 TCP,直接读取到 Content-Length)</summary>
/// <remarks>
/// 命令:dotnet run --project Benchmark/Benchmark.csproj -c Release -- --filter "*HttpStreamBenchmark*"
/// 服务端为内置 HttpServer;客户端为裸 TcpClient(避免 HttpClient 自身开销干扰)。
/// </remarks>
[MemoryDiagnoser]
[SimpleJob(warmupCount: 2, iterationCount: 5)]
public class HttpStreamBenchmark : IDisposable
{
    private HttpServer _server = null!;
    private Byte[] _payload = null!;
    private Byte[] _buf = null!;

    /// <summary>响应体大小(字节)</summary>
    [Params(1024 * 1024, 8 * 1024 * 1024)]
    public Int32 Size { get; set; }

    [GlobalSetup]
    public void Setup()
    {
        _payload = new Byte[Size];
        Random.Shared.NextBytes(_payload);
        _buf = new Byte[64 * 1024];

        _server = new HttpServer { Port = 0 };
        _server.Map("/stream", new StreamBodyHandler { Payload = _payload });
        _server.Map("/buffer", new BufferBodyHandler { Payload = _payload });
        _server.Start();
    }

    [GlobalCleanup]
    public void Cleanup() => _server?.Dispose();

    /// <summary>清理</summary>
    public void Dispose() => Cleanup();

    /// <summary>流式响应:BodyStream 分块发送(大文件不物化)</summary>
    [Benchmark]
    public Int64 StreamBody()
    {
        var total = Get("/stream");

        return total;
    }

    /// <summary>整段响应:Body 物化后一次 Build 发送</summary>
    [Benchmark]
    public Int64 BufferedBody()
    {
        var total = Get("/buffer");

        return total;
    }

    /// <summary>发起 GET 并读取完整响应,返回收到字节数</summary>
    private Int64 Get(String path)
    {
        using var client = new TcpClient();
        client.Connect(IPAddress.Loopback, _server.Port);

        using var ns = client.GetStream();
        ns.ReadTimeout = 30_000;

        var req = $"GET {path} HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n".GetBytes();
        ns.Write(req, 0, req.Length);

        var received = 0L;
        var buf = _buf;
        Int32 n;
        while ((n = ns.Read(buf, 0, buf.Length)) > 0)
        {
            received += n;
        }

        return received;
    }

    /// <summary>流式响应处理器(BodyStream)</summary>
    class StreamBodyHandler : IHttpHandler
    {
        public Byte[] Payload { get; set; } = [];

        public Task ProcessRequestAsync(IHttpContext context)
        {
            context.Response.ContentType = "application/octet-stream";
            context.Response.BodyStream = new MemoryStream(Payload);

            return TaskEx.CompletedTask;
        }
    }

    /// <summary>整段响应处理器(Body 物化)</summary>
    class BufferBodyHandler : IHttpHandler
    {
        public Byte[] Payload { get; set; } = [];

        public Task ProcessRequestAsync(IHttpContext context)
        {
            context.Response.SetResult(Payload);

            return TaskEx.CompletedTask;
        }
    }
}