首页 文章 精选 留言 我的

精选列表

搜索[LLM],共5767篇文章
优秀的个人博客,低调大师

ASP.NET Core 推 LLM token 流实测:每帧 flush 只花 0.14 微秒,200 并发却只快 7.7 倍

用 ASP.NET Core 给大模型做 token 流式输出,最常见的三个焦虑是:**每次 flush 是不是很贵、能不能扛几百个并发连接、慢客户端会不会把内存吃穿**。这三个都在本机实测了一遍,结论和直觉都不太一样。 ## 结论 - **每帧 flush 一点都不贵**:24 字节的 SSE 帧逐帧 flush,单连接 **0.141~0.151 µs/帧**(660~710 万帧/秒),改成 100 帧 flush 一次只快 **1.5~1.7 倍**。一次 2000 token 的回答,服务端推流总成本约 **0.2 毫秒**。 - **并发不线性**:200 条并发连接的总吞吐只到单连接的 **7.7 倍**(4100~5650 万帧/秒),单连接 p50 延迟从 0.3~0.4 ms 涨到 **5.4~7.6 ms**(约 18 倍)。 - **`Results.Stream` 零成本**,和手写 `Response.Body` 完全等价;`IAsyncEnumerable` 每帧快 40%,但它输出的是 JSON 数组,字节数多 44%,而且你控制不了帧格式。 - **慢客户端不吃内存**:读端每 1KB 停 1ms,服务端耗时从 27 ms 拉长到 **7.8 秒**,但 GC 堆恒定 15.5 MB、进程 RSS 恒定 116 MB、全程额外分配 0.3 MB。写操作被背压挡住了,不是排队缓冲。 - 真正该防的是**连接数**和**首字节时间**,不是 flush 频率。 ## 测试方法 环境:.NET 10.0.5 / Apple M4(4P+6E)/ macOS 26.7.1 / Release / Kestrel,客户端与服务端同机走 127.0.0.1 回环。**这个前提很重要——回环没有网络 RTT,下面的绝对值只代表服务端推流成本,不要当成公网性能。** 被测帧是固定 24 字节的一帧 SSE: ```text data: {"i":0,"t":"tok"}\n\n ``` 服务端三个端点,分别是手写流、`Results.Stream` 包装、`IAsyncEnumerable`: ```csharp app.MapGet("/raw/{batch:int}/{n:int}", async (HttpContext ctx, int batch, int n) => { ctx.Response.ContentType = "text/event-stream"; var body = ctx.Response.Body; for (int i = 0; i ` | 0.057 / 0.059 µs | 7,200,001 | 两个结论: - `Results.Stream` 没有额外开销,和手写等价。它值得用,因为能统一返回类型、方便挂过滤器。 - `IAsyncEnumerable` 每帧快 40%,但那是**假快**:它吐的是 JSON 数组的流式序列化结果,字节数多 44%(引号和逗号),而且前端拿到的不是 `text/event-stream` 的 `data:` 帧。**只要有 SSE 协议要求,就别图省事直接 `yield return` 字符串。** ## 四、慢客户端:不炸内存,但把 27 ms 拖成 7.8 秒 20 万帧(约 4.8 MB 数据),逐帧 flush,快读 vs 每读 1KB 停 1ms 的慢读: | 客户端 | 墙钟 | 服务端额外分配 | GC 堆峰值 | 进程 RSS 峰值 | |---|---|---|---|---| | 快读 | 27~29 ms | 0.0 MB | 15.5 MB | 116 MB | | 慢读 | 7837~7846 ms | 0.2~0.3 MB | 15.5 MB | 116 MB | 耗时差 290 倍,**内存却一个字节没多**:GC 堆和 RSS 两轮完全一致。这是 Kestrel 响应管道的有界 `pause/resume` 机制在起作用——管道积压超过 pause 阈值,`WriteAsync` 就真的 `await` 住,直到读端消费到 resume 阈值以下。也就是说: - 慢客户端**不会**让服务端把 4.8 MB 积压塞进内存,写端直接被阻塞; - 但它会**长期占住一条连接和一个异步状态机**,这才是真风险。 所以生产上的防线不在内存,在连接生命周期:`RequestAborted` 要真的传下去、给流式响应设总时长上限、客户端断开要能把上游推理一起取消。否则 200 个半死连接就能把你的实例连接数配额占满,而监控上内存一片平静。 ## 落到生产的三条 1. **别纠结 flush 频率**。逐帧 flush 每帧也就多 0.05 µs,体验优先就逐帧 flush。要省 CPU 就攒 5~20 帧,收益基本吃满,再往上攒没意义,只会让首字变慢。 2. **并发靠分片,不靠加连接**。单实例 200 连接时每用户 p50 已经 5 ms 以上;要更多用户,走多实例 + 前置分流。 3. **慢客户端按连接超时治理,不按内存治理**。背压已经帮你挡住了内存增长,你要补的是超时、取消和连接数上限。 ## 复现 ```bash mkdir SseLab && cd SseLab dotnet new web -f net10.0 # 把上面的三个端点和客户端压测代码写进 Program.cs dotnet build -c Release dotnet bin/Release/net10.0/SseLab.dll server # 一个终端 dotnet bin/Release/net10.0/SseLab.dll bench # 另一个终端 ``` 两个进程要分开跑,压测端在同一进程里会和服务端抢核,数字会整体偏移。测之前记得先预热(我这里是每个端点跑 3 次 1000 帧),否则测到的是 JIT 分层编译的过程,不是稳态。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册