阶段六十九:同进程并发失败恢复
新增可重复的同进程验证工具,复用同一 DocumentEngine 并发执行源读取、源关闭、后端接收、同步取消和输出字节超限五类失败,每次都在同一路径紧接一次成功导出。逐次检查源关闭一次、旧目标保留、原子临时文件清理及恢复输出计数。测试只使用显式字体及合成记录。
初始运行:每种模式 2 个并发线程、5 轮、每次 1,000 行;绘制后丢弃与真实 PDF 合计 20 次失败/恢复循环,恢复 20,000 行,全部 180 个 PDF 页独立核对通过。
扩展运行:每种模式 3 个并发线程、10 轮、每次 1,000 行,单 JVM 最大堆 256 MiB;共 60 次失败/恢复循环,恢复 60,000 行。全部 540 个 PDF 页逐页提取,30 个文件的源行序列、线程/轮次身份、重复表头及文件字节计数均通过,无串扰、重复或丢失。两类进程均正常退出,临时文件数为零。
| 扩展模式 | 恢复输出行 | 耗时 | 轮末观察堆峰 | 采样工作集峰 | 采样私有字节峰 | 采样句柄峰 | 采样临时字节峰 |
|---|---|---|---|---|---|---|---|
| 布局绘制后丢弃 | 30,000 | 1.062 秒 | 31,165,376 | 187,863,040 | 261,181,440 | 451 | 0 |
| 实际 PDF | 30,000 | 39.097 秒 | 116,506,344 | 301,682,688 | 365,981,696 | 480 | 393,216 |
观察堆取各成功轮末采样,不是全过程峰值、强制 GC 后保留堆或 RSS。Windows 工作集/私有字节/句柄按 100 ms 采样,可能遗漏瞬时峰值。临时磁盘覆盖隔离 java.io.tmpdir 和原子目标临时文件,排除最终 PDF。字体 SHA-256 与仓库显式资源、11/293 个进程采样和摘要峰值独立对账。
.\gradlew.bat -g build/gradle-validation :examples:writeStreamingTableClasspath --offline --no-daemon
.\scripts\measure_streaming_stability.ps1 -SkipBuild -Workers 3 -Rounds 10 -Rows 1000
python scripts/verify_streaming_stability.py运行目录使用独立 ID,成功后才更新 build/verification/streaming-stability-directory.txt;原始报告、采样和文件均在忽略目录中保留。脚本对 JVM、每轮导出、同步起点和工作线程收尾分别设上限;只采样并清理自己启动的进程。
这是一组有限的重复/并发/失败恢复证据,未改变生产布局或文件格式,不属于新的视觉行为验收。不能推广为任意并发、长期无泄漏、PDFBox 页树恒内存或硬进程内存上限;长期运行及更多平台仍开放。