解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
|
# 背压水ä½å®šæ¡£ä¸Žå†…å˜æµ‹ç®—报告
> 报告日期:2026-09-17 | 基线:v12 工作区 | 环境:i9-10900K / .NET 10.0.12 / Windows 10 22H2
> å£å¾„:回环 TCP,客户端与æœåŠ¡ç«¯å…±äº« CPU;基准为 BenchmarkDotNet(Release),实验为手动用例(默认跳过)
>
> **åŽç»å˜æ›´ï¼ˆ2026-10-01)**:出站å‘é€é˜Ÿåˆ—(`SendPipe`/`SendPump`)已整å—ç§»é™¤ï¼Œå‡ºç«™æ”¹ç›´å‘ + 一把写é”,**写侧水ä½ä¸Ž `FlushAsync` 挂起ä¸å†å˜åœ¨**ï¼ˆå†™ä¾§èƒŒåŽ‹ç”±å†…æ ¸å‘é€ç¼“冲承担);本报告的**读侧水ä½ï¼ˆå…¥ç«™ 1M/512Kã€æš‚åœæŽ¥æ”¶ä¸Žé¥¥é¥¿è®©ä½ï¼‰ç»“论继ç»ç”Ÿæ•ˆ**,写侧 64K/32K 的定档仅作为历å²è®°å½•(åŽç»ï¼š2026-10-01 åˆåŠ å›žå¯é€‰çš„å‘é€é˜Ÿåˆ— `SendQueue`,其出站水ä½ä¸º 256K/128Kï¼›é»˜è®¤è·¯å¾„ä»æ— 应用层出站水ä½ï¼‰ã€‚
---
## 1. ç›®æ ‡
为 `NewLife.Data.Pipe` 背压水ä½é»˜è®¤å€¼å®šæ¡£â€”—**读侧**ï¼ˆä¼šè¯æŽ¥æ”¶ç®¡é“)与**写侧**(当时的å‘é€ç®¡é“)分侧决ç–,替æ¢"读写共用 1M/512K ä¸”æ— è®ºè¯"çš„çŽ°çŠ¶ï¼›åŒæ¥ä¿®å¤æ‰§è¡Œä¸å®žæµ‹å‘现的**读饥饿æ»é”**。
## 2. 背景
- 机制:迟滞水ä½ï¼ˆè¾¾åˆ° `PauseThreshold` æš‚åœã€é™åˆ° `ResumeThreshold` 以下æ¢å¤ï¼‰ã€‚è¯»ä¾§æš‚åœ = æŽ¥æ”¶çŽ¯æš‚å˜ SAEA(`ParkReceive`),æ¢å¤åŽé‡å¯ï¼›å†™ä¾§æš‚åœ = `FlushAsync` 挂起生产者。
- 原默认:1M/512K(读写共用)。
- 竞å“å¯¹ç…§ï¼ˆå®˜æ–¹èµ„æ–™æ ¸éªŒï¼‰ï¼šBCL `PipeOptions.Default` 64K/32K(通用管é“);Kestrel `MaxRequestBufferSize` 默认 **1MB**(入站缓冲上é™ï¼‰ã€`MaxResponseBufferSize` 默认 **64KB**(出站阻塞阈值,与 `FlushAsync` 挂起åŒè¯ä¹‰ï¼‰ï¼›Netty `WriteBufferWaterMark` 默认 32K/64K(写侧 `isWritable` æç¤ºè¯ä¹‰ï¼‰ã€‚
## 3. 关键结论(摘è¦ï¼‰
1. **写侧定档 64K/32K**(原 1M/512Kï¼‰ï¼šå¯¹é½ BCL/Kestrel 出站档;8MB æµå¼å‘é€å„æ¡£ä½åžåæ— å·®å¼‚ï¼ˆ4.7–5.4ms);慢对端下æ¯è¿žæŽ¥æŽ’é˜Ÿå†…å˜æœ€åé™ 16×。
2. **è¯»ä¾§ç»´æŒ 1M/512K**:与 Kestrel 入站 1MB åŒé‡çº§ï¼›1M 档暂åœ/æ¢å¤æ¬¡æ•°æœ€å°‘(慢消费下 churn 低约一个数é‡çº§ï¼‰ï¼›32MB å¿«æ¶ˆè´¹æŽ¥æ”¶å„æ¡£ä½æ— 差异(23.1–23.6ms)。
3. **ä¿®å¤è¯»é¥¥é¥¿æ»é”**(执行ä¸å®žæµ‹å‘现):暂åœä¸€æ—¦è§¦å‘ï¼Œæ•´å¸§è¯»å–æ— æ³•è§£é™¤â€”â€”è¯»è€…æ— æ³•æ¶ˆè´¹ï¼ˆå¸§ä¸å®Œæ•´ï¼‰ã€æ¶ˆè´¹ä¸ºé›¶äºŽæ˜¯æ°¸ä¸æ¢å¤ï¼Œå¸§æ°¸è¿œå‡‘ä¸é½ï¼›å®žæµ‹èŒƒå›´ä¸º"**ä»»ä½•è·¨è¿‡æš‚åœæ°´ä½è¾¹ç•Œçš„帧**"。修å¤åŽ 32MB 会è¯åŽ‹æµ‹ç”± 30s è¶…æ—¶å˜ä¸º <0.5s 完æˆã€‚
## 4. 缺陷记录与修å¤ï¼ˆè¯»é¥¥é¥¿è®©ä½ï¼‰
- **å¤çް**:`PipeWatermarkReceiveBenchmark`(32MB/轮,64K 档)两次在第二轮调用挂起;会è¯çº§åŽ‹æµ‹ç”¨ä¾‹è¿žç» 7 次 30s è¶…æ—¶ã€‚åœæ‘†çŽ°åœºï¼š`已收 0/1024ã€æš‚åœ=Trueã€æœªæ¶ˆè´¹=16384`(æ°å¥½ä¸€ä¸ªæ°´ä½ï¼‰ã€‚
- **机ç†**:整帧读å–对ä¸å®Œæ•´å¸§ä¸æ¶ˆè´¹ï¼ˆ`AdvanceTo(0, examined)`);暂åœè§¦å‘åŽæŽ¥æ”¶åœæ‘†ï¼›è¯»è€…ç‰å¾…çš„åŽç»§å—节ä¸ä¼šåˆ°è¾¾ï¼›æ¶ˆè´¹ä¸ºé›¶ → `Resumed` æ°¸ä¸è§¦å‘ → æ»é”(对端关é—亦ä¸å¯æ„ŸçŸ¥ï¼Œç›´åˆ°ç©ºé—²è¶…时)。
- **ä¿®å¤ Aï¼ˆæ ¸å¿ƒï¼‰**:`PipeReader.ReadAsync` 在"æ— æ–°æ•°æ®å°†æŒ‚èµ·ç‰å¾…"时调用 `Pipe.ReleasePauseForReaderLocked` 解除暂åœå¹¶è§¦å‘ `Resumed`(**读饥饿让ä½**)——背压约æŸ"已到达未检查的积压"ï¼Œä¸æŸç¼šè¯»è€…æ£åœ¨ç‰å¾…的数æ®ã€‚
- **ä¿®å¤ Bï¼ˆåŠ å›ºï¼‰**:`TcpSession.ParkReceive` å˜å…¥æš‚å˜åŽå¤æŸ¥æš‚åœæ€ï¼Œè‹¥åœ¨"è¯»å–æš‚åœæ€ä¸Žæš‚å˜è½ä½"之间已å‘生æ¢å¤ï¼Œåˆ™ç«‹å³é‡å¯ï¼ˆä¸¢å”¤é†’防护)。
- **契约å˜åŒ–**:原"整帧大于水ä½ä¼šåœæ‘†"ä¸å¤å˜åœ¨ï¼›å¤§å¸§ç»æ•´å¸§è·¯å¾„å¯å®Œæˆï¼ˆè¯¥å¸§é©»ç•™å†…å˜éšå¸§é•¿å¢žé•¿ï¼Œè¶…大 payload 建议头部先行æµå¼ï¼‰ã€‚新增用例 `SessionPipe_WholeFrameExceedsPauseThreshold_ReaderStarvationReleases`ã€`SessionPipe_Backpressure_HighFrequencyPauseResume` é”定。
- **验è¯**:`SessionPipeTests` 5/5 è¿žç» 3 轮(<0.5s);接收基准 3 æ¡£ä½å®Œæ•´è·‘å®Œï¼›å…¨é‡ 2920 ä¾‹ä¸ 2904 通过ã€15 è·³è¿‡ï¼ˆå«æœ¬æŠ¥å‘Š 3 个手动实验)ã€1 例 `TarEntryTests` 为仓库已知并å‘å¶å‘(å•独å¤è·‘通过);18 TFM 构建 0 错。
## 5. 基准数æ®ï¼ˆBenchmarkDotNet,Release)
命令:`dotnet run --project Benchmark/Benchmark.csproj -c Release -- --filter "*PipeWatermark*"`
### 5.1 写侧:8MB `SendAsync(Stream)`(快对端)
| æš‚åœæ°´ä½ | Mean | StdDev |
|---------:|-----:|-------:|
| 64K | 4.888 ms | 0.130 ms |
| 128K | 5.288 ms | 0.106 ms |
| 256K | 4.710 ms | 0.043 ms |
| 1M | 5.370 ms | 0.338 ms |
→ 差异在置信区间内,**æ— æ¡£ä½æ•感**。
### 5.2 读侧:32MB 定长帧接收(快消费)
| æš‚åœæ°´ä½ | Mean | StdDev |
|---------:|-----:|-------:|
| 64K | 23.61 ms | 0.714 ms |
| 256K | 23.13 ms | 0.203 ms |
| 1M | 23.25 ms | 0.084 ms |
→ ≈1.37GB/s,**æ— æ¡£ä½æ•感**(水ä½åªå½±å“慢消费内å˜ä¸Žæš‚åœé¢‘率)。
## 6. 实验数æ®ï¼ˆæ…¢æ¶ˆè´¹ / 慢对端 / 大帧)
命令:`dotnet test XUnitTest.Core -f net10.0 --filter "FullyQualifiedName~WatermarkExperimentTests" --logger "console;verbosity=detailed"`
### 6.1 读侧慢消费(4.9MB,消费≈16MB/s)
| æ°´ä½ | 峰值积压 | 内å˜å¢žé‡å³°å€¼ | æš‚åœæ¬¡æ•° | æ¢å¤æ¬¡æ•° | 耗时 |
|-----:|---------:|-------------:|---------:|---------:|-----:|
| 64K | 71 KB | 453 KB | 24 | 99 | 2314 ms |
| 256K | 263 KB | 521 KB | 24 | 29 | 2315 ms |
| 1M | 1031 KB | 8 KBï¼ˆé‡‡æ ·å™ªå£°ï¼‰ | 4 | 7 | 2342 ms |
→ 峰值积压 ≈ æ°´ä½ + 1 å—æŽ¥æ”¶ç¼“å†²ï¼ˆ8K);æ¢å¤æ¬¡æ•°éšæ°´ä½ç¼©å°å¢žé•¿çº¦ä¸€ä¸ªæ•°é‡çº§ï¼›æ€»è€—æ—¶ç”±æ¶ˆè´¹æ–¹å†³å®šï¼Œä¸Žæ°´ä½æ— 关。
### 6.2 写侧慢对端(4MB,对端≈6.4MB/s)
| æ°´ä½ | 峰值队列 | æ¢å¤æ¬¡æ•° | 生产者耗时 | 端到端 |
|-----:|---------:|---------:|-----------:|-------:|
| 64K | 64 KB | 64 | 46 ms | 1027 ms |
| 128K | 64 KB | 31 | 32 ms | 994 ms |
| 256K | 192 KB | 16 | 27 ms | 990 ms |
| 1M | 1024 KB | 3 | 29 ms | 991 ms |
→ 队列峰值 ≤ æ°´ä½ï¼ˆä½Žæ¡£ä½ç”± OS 套接å—ç¼“å†²å¸æ”¶ï¼Œæ˜¾ç¤ºæ›´ä½Žï¼‰ï¼›ç”Ÿäº§è€…与端到端ä¸å—æ¡£ä½å½±å“。
### 6.3 大帧æµå¼ï¼ˆ8MB å•帧,头部先行,修å¤åŽï¼‰
| æ°´ä½ | 耗时(3 轮) | 峰值积压 | æš‚åœ/æ¢å¤ |
|-----:|-------------|---------:|----------:|
| 64K | 9 / 4 / 4 ms | 64 KB | 6–9 / 115–128 |
| 1M | 4 / 4 / 4 ms | 32–64 KB | 0 / 0 |
→ 64K 档完æˆä¸å—阻,但å˜åœ¨**让ä½å¾ªçޝ**(churnï¼šæš‚åœ â†’ 读者饥饿 → è®©ä½æ”¾è¡Œï¼Œæ¯çº¦ä¸€ä¸ªæ°´ä½å—节一轮);1M 档零暂åœâ€”—大帧æµå¼åœºæ™¯æ”¯æŒç»´æŒ 1M 读侧默认。
## 7. å†…å˜æµ‹ç®—(最å驻留)
å•连接最å:读侧 ≈ æ°´ä½ + 1×接收å—(8K);写侧 ≈ æ°´ä½ + 1׿µå¼å—(64K)。仅"消费è½åŽ / 对端慢"的连接å‘生驻留,æ£å¸¸æ¶ˆè´¹ä¸ç§¯ç´¯ã€‚
| æ¡£ä½ | å•连接(读/写) | 10 万暂åœè¿žæŽ¥ï¼ˆè¯»/写) | 100 万暂åœè¿žæŽ¥ï¼ˆè¯»/写) |
|------|-----------------|------------------------|--------------------------|
| 64K | ~72K / ~128K | 7.2 GB / 12.8 GB | 72 GB / 128 GB |
| 256K | ~264K / ~320K | 26 GB / 32 GB | 264 GB / 320 GB |
| 1M | ~1.03M / ~1.09M | 103 GB / 109 GB | 1030 GB / 1090 GB |
("全部连接暂åœ"为æžç«¯ä¸Šç•Œï¼Œä»…用于比较档ä½é—´æ•°é‡çº§å·®å¼‚。)
## 8. 定档结论
| ä¾§ | 原值 | 定档 | 便® |
|----|------|------|------|
| 读侧(入站) | 1M/512K | **ç»´æŒ 1M/512K** | Kestrel 入站åŒé‡çº§ï¼ˆ1MBï¼‰ï¼›æš‚åœ churn 最低(1M æ¡£ 7 次 vs 64K æ¡£ 99 次);大帧ç»é¥¥é¥¿è®©ä½ä¸å—阻;慢消费内å˜å®‰å…¨é˜€ |
| 写侧(出站) | 1M/512K | **64K/32K** | å¯¹é½ BCL 通用默认与 Kestrel 出站阻塞阈值(64KB);实测åžåæ— é€€åŒ–ï¼›æ…¢å¯¹ç«¯æŽ’é˜Ÿå†…å˜æœ€åé™ 16× |
- **读写éžå¯¹ç§°**(读宽写紧):与 Kestrel çš„ `MaxRequestBufferSize`(1MB) / `MaxResponseBufferSize`(64KB) éžå¯¹ç§°å¸ƒå±€ä¸€è‡´ã€‚
- **倿•°å£å¾„ç”å¤ï¼ˆBufferSize 倿•°ææ¡ˆï¼‰**:读侧 1M = 128×8Kã€512K = 64×8K,å¯ä½œæ–‡æ¡£å£å¾„(与 `SocketSetting.BufferSize` 注释å£å¾„一致);**ä¸åšä»£ç 层按 `BufferSize` 推导**â€”â€”å†™ä¾§ä¸ŽæŽ¥æ”¶å—æ— 机ç†å…³ç³»ï¼Œä¸”推导会让调整 `BufferSize` æ„外改å˜èƒŒåŽ‹è¡Œä¸ºï¼Œä¿æŒä¸¤æ—‹é’®ç‹¬ç«‹ã€‚
## 9. å±€é™
- 回环å£å¾„(客户端与æœåŠ¡ç«¯å…±äº« CPU),跨机/真实网络下的ç»å¯¹å€¼ä¼šä¸åŒï¼›ç»“论基于档ä½ä¹‹é—´çš„相对比较。
- æ…¢å¯¹ç«¯å®žéªŒä¸ OS 套接å—ç¼“å†²ä¼šå¸æ”¶éƒ¨åˆ†æ•°æ®ï¼ˆé˜Ÿåˆ—峰值低于档ä½ï¼‰ï¼›ç®¡é“层最å驻留以第 7 节算术为准。
- 实验用例为手动采集(默认 `Skip`),用于å¤çŽ°ä¸Žå¤æ ¸ï¼Œä¸å‚与常规回归。
## 10. 相关产物
- 基准:`Benchmark/StreamingBenchmarks/WatermarkBenchmarks.cs`(`PipeWatermarkSendBenchmark` / `PipeWatermarkReceiveBenchmark`)
- 用例:`XUnitTest.Core/Net/SessionPipeTests.cs`ï¼ˆè¯»é¥¥é¥¿è®©ä½ / 丢唤醒压测)ã€`XUnitTest.Core/Net/WatermarkExperimentTests.cs`(手动实验)
- ä¿®å¤ï¼š`NewLife.Core/Data/Pipe.cs`(`ReleasePauseForReaderLocked`)ã€`NewLife.Core/Data/PipeReader.cs`(挂起路径让ä½ï¼‰ã€`NewLife.Core/Net/TcpSession.Stream.cs`(`ParkReceive` 夿Ÿ¥ã€å‡ºç«™æ°´ä½ 64K/32K)
|