Repository navigation
perf: bound recent rollout history reads - #7700
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
songoow
left a comment
There was a problem hiding this comment.
Reviewer: model_agent — GPT-6 Astra Pro — OpenAI — self_reported
动机 / Motivation
Todo 读取和状态等只需要最近一段 rollout 记录的真实调用方,会随着项目历史增长重复读取整个 JSONL 文件。
原实现虽然最终只返回最近 N 条有效记录,仍从头扫描全部历史;本 PR 在正 limit 且文件可 seek 时从尾部按块读取,仍返回同一组有效记录及时间顺序。无界读取与不可 seek 输入继续走既有完整/顺序语义。
相同 20,000 行、18,217,779 字节历史下,实际 File/SQLite todo list 读取从全文件降到 458,752 字节,两端公开结果完整一致,原 authority revision 和历史文件保持。这里度量读取字节,不宣称墙钟提速或所有 provider 的长期性能。
本次不删历史、不截断调用方需要的有效结果,也不改变 quota/回执权威或追加协议;不引入缓存、迁移、跨进程快照或新的并发保证。
改动思路 / Approach
这是已有读取 owner 内的算法调整,不是新的历史权威。统一 parser 维持有效记录定义,tail iterator 只减少正 limit 的物理读取;消费者要求的完整结果、时序和当前 authority 都保留。
范围止于 recent-reader 和回归;无界日志、追加写入、Goal provider 及业务判定不变。当前证据证明合成同负载真实 CLI 的 IO 改善,未延伸成生产长时吞吐资格。
Todo 调用原 canonical authority 获取状态,再按既有 limit=500 读取 rollout 观察。新 reader 从文件尾拼接完整字节行,共用原解析规则,够 500 条有效记录后停止并恢复原顺序;没有有效 limit 或输入不可 seek 时沿用原行为,读取中不修写数据。
原 loader 已是各调用方共享的读取 owner,直接在这里复用同一行解析规则并改变有界 IO 足够。另建索引文件、全局缓存或要求消费方重复裁剪都会增加状态与失效规则;它们并非本次成本问题所必需。
具体改动 / Changes
关键代码讲解
- _parse_rollout_event_line:共享原有行解析合同。正向与反向读取使用同一 blank/JSON/object/schema 校验;tolerant 跳过坏行,strict 继续给出原行号诊断,不因优化放宽输入。
- _reverse_rollout_lines:只改变有界读的物理遍历。从末尾按 64 KiB 块读取,先拼完整行再解码,支持跨块长 Unicode 行和无最终换行,避免字符或记录被切坏。
- _recent_rollout_events:保留最近有效记录及输出顺序。只对有效事件计数,凑够调用方 limit 后停止,按原时间顺序返回;不可 seek 的输入保留正向有界 deque。
- load_rollout_events:把新算法限定在现有正 limit 分支。None、0 和负值继续完整读取;现有无界恢复调用不因这个优化丢历史。
规范基准:docs/development/testing-and-quality.md;修订 a36e01c。没有独立新功能 RFC;这是既有 recent-reader 的有界实现。以基线的 Refactor Real-Path Gate 和 Roadmap-Aligned Optimization 约束验证,具体返回语义来自改动前公开 loader 与真实调用方,而非新 helper 自定义的输出。
| Criterion | 当前结论 | 对应实现或剩余边界 |
|---|---|---|
| Refactor Real-Path Gate | implemented | load_rollout_events, shared _parse_rollout_event_line and real todo list readback |
| Locate the cost before selecting an abstraction | implemented | _reverse_rollout_lines -> _recent_rollout_events for limit > 0 |
| Share contracts, qualify implementations | implemented | Existing callers keep their limits; unlimited and nonseekable branches retained |
实际验证 / Validation
本轮 exact head 的 tests/test_rollout_event_log_loading.py 共 29 个案例全部通过。覆盖跨块长 Unicode、坏 JSON/非对象/错误 schema/非 UTF-8、空行、缺末尾换行、不同正 limit、None/0/负值全读、nonseekable fallback、strict 行号、后续 append 可见以及保留对象/读取字节的界限。
另用相同 SHA256 20040eaa0cc08e244e0a3a7b8a33fac8499ab7e4d7b7aa7ccd0f4b3a6104aaa5 的 20,000 行历史,在 base/head 的真实 todo list 路径分别运行 File 与 SQLite。两种 provider 都从读取 18,217,779 字节降到 458,752 字节;每次只打开一次实际日志。完整规范化输出相同,且调用后的 authority revision 和历史字节未变。File 输出指纹 7f3046e2d4ed7d65164fe0ceaac2493cd96bc45c132a1016468518cb96188857,SQLite 为 a83f33128716e11a261d178f89e736e49c6c9833e85773292ea08d70a3dfb2a5。旧实现读完整文件,无法满足同一有界读取断言;候选满足。没有用并发测试期间的墙钟数字推断性能增益。 额外独立字节 oracle 又实际执行同一公开 CLI:base 在 18,217,779 ≥ 4,554,444 的断言处退出 1;head 两个 provider 均以 458,752 字节通过,退出 0。这个对照使用原 20,000 行负载和同一阈值,不是只对保存的数字做推断。
对主干的风险 / Risks
主要风险是把反向物理遍历错误地变成反向结果、切坏长 UTF-8 行、让坏行吃掉有效记录额度,或误伤需要全历史的恢复调用。共享 parser、完整行组装和仅限正 limit 的入口约束与回归均覆盖这些边界;没有引入缓存失效或数据迁移。未发现阻断性实现问题,超长单条记录仍可能要求相应缓冲,这是完整记录合同本身的成本。
语义与 CI 对齐
对照标准是既有 loader/真实消费者以及基线工程文档的完整语义与 IO 规则。这里没有截历史、缩 workload、放宽阈值或删输出;受益限于请求最近记录的物理 IO,不能代表其他历史消费者也自动变快。
当前 Linux shard 5 红,其日志在两次有界读取中都遇到传输失败,尚未归因。Windows 日志可得,四个失败位于 self_update_runtime_activation 的 python_pip/pipx 安装路由与 archive override 场景,另 415 通过、20 跳过;未运行原生 Windows 基线,故不宣称这些是已证历史噪声。checks/pytest/merge gate 仍不是绿色,本地结论仅针对已直接验证的 loader 与真实 consumer。
当前阻断是验证缺口,不是凭红灯虚构的代码 finding。 仓库当前 verdict_policy 明确未归因的 current failures 阻止批准;仅证明变更文件不在失败路径,尚不足以归类 pre_existing。最小解除条件是对上述具体失败提供不可变 base/head 的同命令、同签名对照,或独立证明外部/环境原因并补齐受影响合同的当前资格;若归因确属回归,再修相应代码。本轮不要求为未归因失败修改无关代码,也不放宽已有预算。
我的整体评价 / Verdict
REQUEST_CHANGES:未发现阻断性的代码缺陷;当前 CI 失败尚缺政策要求的归因证据,因此暂不具备批准资格。 审查绑定 exact head 7243b4c。
长期历史仍完整保留,原状态与回执 owner 没有变化。实际有界消费者不再每次读取全部旧历史,有直接 IO 依据;无界恢复消费者仍可读全量,不能把这个局部收益等同长期运行容量或并发资格。
对用户可见的最近记录、顺序与 Todo 输出保持,损坏行容忍和严格错误诊断也保留。没有要求用户归档、清理历史或额外确认才能获得收益。 该改动是日志读取算法,未改变页面布局或 UI 交互;实际 CLI 完整读回已比较。
共享 parser 加一个局部 tail iterator 已满足有界读取;继续保留无界与不可 seek fallback 是兼容合同所需,不是待删除的重复 owner。当前没有证据支持引入索引服务或全局缓存。
本轮使用隔离的合成持久化历史和真实 File/SQLite CLI,量的是读取字节;未测安装后生产吞吐、原生 Windows、远程 provider 或并发追加快照。远程 Linux 日志不可得、Windows 失败尚未做基线归因,完整合并资格仍有这些限制。
English verdict: REQUEST_CHANGES — exact head 7243b4c; Current required CI failures lack the repository-required attribution, so approval is withheld. No blocking code defect was found in the exercised change; resolve the named validation gap rather than changing unrelated code.
…d-rollout-read-20261030 Signed-off-by: huangruiteng <huangrt01@163.com>
songoow
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; GPT-6; OpenAI; self_reported.
动机 / Motivation
受影响的是从长期rollout历史中读取最近N条记录的Task/status调用者。以前带limit仍顺序解析所有旧历史;本项从文件尾反向装配完整行,得到足够合法记录后停止。已验证最近窗口保留时间顺序、完整Unicode、损坏行容忍与非seekable回退,并保持严格完整扫描入口。本项不删历史、不改事件schema,也不为完整账务或严格审计截取历史。
这次判断绑定PR #7700的完整head c1adf9f。评价对象是已经存在的实际调用任务与局部可观察结果;重复调用带来的成本或错误恢复路线是本项动机,不能把较小响应或更少导入直接等同于长期任务质量。
改动思路 / Approach
_recent_rollout_events用deque保持最近窗口,seekable文件逆读,非seekable保留顺序fallback;无限读取仍调用原完整iterator。本 PR 的合理边界是有界历史读取的文件适配器,不增加状态索引、后台缓存或另一套事件分类规则。
沿入口跟踪到原所有者、返回值和失败恢复后,这个实现仍在现有边界上处理问题。无改动会保留原成本或错误指引;另起一套业务规则、持久化状态或通用缓存会增加同步义务,此处没有这类必要性。新增说明和投影应服务原调用方完成任务,不能改变原来的准入、权限、结算或来源完整性要求。
具体改动 / Changes
关键代码讲解
- _reverse_rollout_lines:按64KiB块逆向读取并拼出完整行后才解码,避免切断大行/UTF-8。 输入与拒绝分支沿用现有调用路径;这一处的返回内容或依赖时机改变,不把局部投影提升为新的业务判定。
- _recent_rollout_events:略过不合法行,只在足够有效记录时停止,并appendleft恢复原顺序。 输入与拒绝分支沿用现有调用路径;这一处的返回内容或依赖时机改变,不把局部投影提升为新的业务判定。
- load_rollout_events:仅正数limit走新路径,None或非正值继续完整读取。 输入与拒绝分支沿用现有调用路径;这一处的返回内容或依赖时机改变,不把局部投影提升为新的业务判定。
全量/严格历史消费者仍有原入口;有界路径只改变读取范围与解析成本,不把窗口缺失当权威状态不存在。正向场景是:近N条合法记录保持原有完整内容与顺序,旧历史无须先解析。负向场景是:超长行、缺失文件、损坏JSON/UTF8、无末换行与非seekable来源保留原安全边界。这些是依据实际源码与已有调用测试核对的行为边界;失败和恢复继续由原owner负责,没有以返回字段存在代替真实状态读取。
规范依据为原公开调用行为、既有所有者和相应回归;已检索改动路径与周边文档,没有为这次局部性能/适配修正找到另一个已接受专项RFC。作者的量测叙述不充当独立功能合同。
实际验证 / Validation
40项rollout loading及status snapshot回归 PASS,覆盖顺序、严格解析、损坏行、多字节字符、尾部有界读取和非seekable回退;Python编译与 diff hygiene PASS。
执行命令:python -m pytest -q tests/test_rollout_event_log_loading.py tests/control_plane/test_status_rollout_event_snapshot.py。本轮统计只包含上述实际执行;作者PR内微基准、旧head完整回归和旧review的历史量测都已阅读,但不冒称本轮重新执行的结果。
对主干的风险 / Risks
全量/严格历史消费者仍有原入口;有界路径只改变读取范围与解析成本,不把窗口缺失当权威状态不存在。最需要防止的情况是:超长行、缺失文件、损坏JSON/UTF8、无末换行与非seekable来源保留原安全边界。已核对相关调用方和已有review,未重复发布旧head意见;本轮对新增head的源代码与局部回归单独作判断。原持久化状态和业务所有者保持,仍然不能由小范围通过推断整仓或所有部署入口已经合格。
当前精确head失败证据:test-shard (3)、test-shard (2)、test-shard (4)。当前多个test-shard失败/取消缺少可核验日志;本轮未对原生Windows与完整安装后路径重新验证,不能宣称全平台资格。 未取得的分片日志明确留作未知;同名错误或改动文件不相交都不足以建立pre_existing归因。
最小补齐是针对当前实际失败取得日志,并提供不可变base/head同命令同条件归因,或能独立覆盖该失败不变量的当前真实入口证据。已完成的聚焦回归不应无条件重做,也不要求无关功能重写;如果归因确认是回归,再修相应最小代码路径。未完成的检查不是单凭pending就要求改代码的理由。
我的整体评价 / Verdict
REQUEST_CHANGES:当前阻断是具体的验证证据缺口。聚焦审查尚未发现可复现的阻断性生产代码缺陷,不能把未归因红灯写成代码finding。 审查仅适用于exact head c1adf9f。
本 PR 的合理边界是有界历史读取的文件适配器,不增加状态索引、后台缓存或另一套事件分类规则。 已验证最近窗口保留时间顺序、完整Unicode、损坏行容忍与非seekable回退,并保持严格完整扫描入口。 已检查 loopx/rollout_event_log.py:_reverse_rollout_lines;loopx/rollout_event_log.py:_recent_rollout_events;loopx/rollout_event_log.py:load_rollout_events;变更是CLI/内部读取或文本协议,没有修改浏览器页面布局,视觉截图不适用。
当前多个test-shard失败/取消缺少可核验日志;本轮未对原生Windows与完整安装后路径重新验证,不能宣称全平台资格。 本项不删历史、不改事件schema,也不为完整账务或严格审计截取历史。所有本轮探针使用合成fixture,没有运行真实模型任务或发起业务作业;本review陈述审查与验证事实,不声称已经发布部署或完成合并。
English verdict: REQUEST_CHANGES — exact head c1adf9f. Focused code review and the listed local regressions found no confirmed blocking implementation defect. Approval is held for the named current validation gaps; resolve their source-bound evidence rather than changing unrelated code.
Goal And Delivered Outcome
load_rollout_events(limit=...)still read and parsed the entire retained JSONL log.loopx-project/loopx:main; self-contained maintenance repair.Author Declaration
Implemented against
load_rollout_events_recent_rollout_eventsiter_rollout_events, recent readerScope And Continuation
Validation
7243b4ce51739eb440a44537ee9fd54d82002e2f.Complete CLI comparison at the unchanged head
Compared
a36e01c32b0a290a96466c766629a0b01850f823with7243b4ce51739eb440a44537ee9fd54d82002e2fthrough the actualscripts/loopx→ Python → TypeScript → canonical-providertodo list --todo-idpath. Both source archives used Python 3.12.15, Node 24.21.0 and SQLite 3.53.4, the same 20,000-event synthetic history, and the same complete long Unicode task and note. All 28 reads succeeded; complete normalized outputs matched, with only the existing validated observation clocks excluded. Canonical revisions and history bytes remained unchanged.These are observations on a busy shared host, not stable p95 or a frozen-budget pass. Five SQLite warm pairs improved and one was slower. The first request to each source worker was 3.689 s versus 3.837 s, so cold-start improvement is unproven. Both owned workers exited normally; no installed application or active Goal was used as a test fixture. The initial private harness incorrectly treated the display
sourcelabel as backend identity; its failed assertion was retained and corrected to verify canonicalauthority_read, without changing product behavior or acceptance conditions.Frontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
N/A: no authority-store, provider/default, routing or compatibility-projection change, and no migration milestone claim.
Boundary Checklist