Skip to content

perf(scale): 50k 压测 harness + resume 计数与 CI artifact 修复 - #3

Merged
FPSZ merged 4 commits into
FPSZ:collabfrom
wjs480:fix/perf-scale
Sep 16, 2026
Merged

FPSZ merged 4 commits into
FPSZ:collabfrom
wjs480:fix/perf-scale

Conversation

@wjs480

@wjs480 wjs480 commented Sep 14, 2026

Copy link
Copy Markdown

背景

评审对压测部分只提了两条:if: always() 与 resume 计数。本 PR 把压测 harness 与这两处修复放在一起。

包含内容(3 个提交)

  1. perf(scale): 压测 harness 支持续跑与断言,新增 50k CI 复跑 workflow(原提交)
  2. perf(scale): 修复压测 harness 的 resume 重复计数与 CI artifact 上传
    • resume 重复计数--start-doc 早于实际进度时,重复写入的文档会替换旧 chunk;原实现用"库里已有数 + 本次写入数"累加 → 重复计数、虚报 indexed_chunkschunks/s。现改为以 DB 实际 chunk 数为准
    • artifact if: always():断言失败时才是最需要看报告的时候,原来恰好在那时丢掉 artifact。
  3. docs(release): 补齐 1.5.2 release notes 与文档索引 —— 让 lint 的版本一致性检查能过(原因同 PR ①)

验证

  • cargo test --workspace --all-targets 全绿,0 失败
  • 基于 collab 最新 050c690behind_by=0

Sourcery 总结

新增可恢复的 5 万规模性能验证,提供可靠的指标、即使失败也能保留的报告,以及更新后的发布文档。

新功能:

  • 新增可配置的 5 万规模性能工作流,支持手动运行和定时运行、竞争阈值及报告构件。
  • 扩展性能测试框架,支持可恢复索引和竞争因子断言。

错误修复:

  • 通过报告数据库中的实际分块数量,防止恢复的基准测试运行因替换分块而重复计数。
  • 即使竞争断言失败,也始终上传 CI 构件,以保留性能报告。

增强功能:

  • 记录 1 万和 5 万规模的基准测试结果、CI 使用方法、性能边界,以及剩余的文档召回瓶颈。

CI:

  • 新增支持定时触发和手动触发的规模性能 CI 工作流,并支持配置文档数量、查询数量和竞争阈值参数。

文档:

  • 新增 1.5.2 版本发布说明,并更新文档索引和 README 中的性能状态。
Original summary in English

Sourcery 总结

建立可恢复的 5 万规模性能验证机制,提供可靠的指标、在失败时保留报告的 CI,以及一致的发布文档。

新功能:

  • 添加可配置的 5 万规模性能工作流,支持定时和手动执行、争用阈值以及报告构建产物。
  • 扩展性能测试框架,支持可恢复的索引和争用因子断言。

错误修复:

  • 根据数据库中的实际分块总数计算恢复后的基准测试计数,避免文档重写时指标被重复计数。
  • CI 断言失败时始终上传性能报告,以保留诊断构建产物。

增强功能:

  • 记录 1k、10k 和 50k 基准测试结果、争用限制、延迟特征以及剩余的文档召回瓶颈。

CI:

  • 添加定时和手动参数化的规模性能 CI 覆盖,并支持配置文档数量、查询数量和争用阈值输入。

文档:

  • 添加 1.5.2 版本发布文档,并更新文档索引和 README 中的性能状态。
Original summary in English

Summary by Sourcery

Establish resumable 50k-scale performance validation with reliable metrics, failure-preserving CI reports, and aligned release documentation.

New Features:

  • Add a configurable 50k-scale performance workflow with scheduled and manual execution, contention thresholds, and report artifacts.
  • Extend the performance harness with resumable indexing and contention-factor assertions.

Bug Fixes:

  • Base resumed benchmark counts on the database's actual chunk total to prevent duplicate-counted metrics when documents are rewritten.
  • Always upload performance reports when CI assertions fail so diagnostic artifacts are retained.

Enhancements:

  • Document 1k, 10k, and 50k benchmark results, contention limits, latency characteristics, and the remaining document-recall bottleneck.

CI:

  • Add scheduled and manually parameterized scale-performance CI coverage with configurable document, query, and contention-threshold inputs.

Documentation:

  • Add 1.5.2 release documentation and update the documentation index and README performance status.

- perf_scale.rs: --start-doc 断点续跑参数(50k 压测期间遗留未提交)

- perf_scale.rs: --max-contention-factor 断言,超标非零退出(供 CI 门槛,目标小于 2x)

- 新增 .github/workflows/perf-scale.yml:手动触发 + 每周日 02:34 UTC 全量 50k,报告 JSON 上传 artifact

- README/PERF_SCALE_50K.md:同步 50k 验证结论与 CI 复跑说明
resume 场景下 --start-doc 可能早于实际进度,重复写入的文档会替换旧 chunk,原实现用'库里已有数 + 本次写入数'累加会重复计数、虚报 indexed_chunks 与 chunks/s;改为以 DB 实际 chunk 数为准。

CI 侧给 artifact 上传加 if: always():断言失败时才是最需要报告的时候,原来恰好在那时丢掉报告。
当前 workspace/UI/Tauri 版本均为 1.5.2,但 docs/release 只有到 v1.5.0,lint job 的版本一致性检查因此必然失败(上游 collab 本身也缺)。补齐 RELEASE_NOTES_v1.5.2.md,覆盖本次工程硬化与 OCR 变更、已知边界与升级说明。

同时把 docs/README.md 的 Release 索引补上 v1.5.0 与 v1.5.2 两条(此前 v1.5.0 也未登记)。
@sourcery-ai

sourcery-ai Bot commented Sep 14, 2026

Copy link
Copy Markdown

审查者指南

本 PR 建立了可手动或定时复跑的 50k 压测 CI,并在 harness 中加入断点续跑、真实 chunk 计数和争用系数断言;同时修复失败时报告 artifact 丢失问题,补充规模验证文档及 1.5.2 release notes 以完成文档和版本一致性。

可恢复性能规模索引与报告的时序图

sequenceDiagram
    participant CI as PerfScaleCI
    participant Harness as perf_scale
    participant Store as VectorStore
    participant DB as SQLiteDB

    CI->>Harness: Run with --start-doc and --report
    alt start_doc == 0
        Harness->>Store: purge_all_index_data()
        Harness->>Store: begin_full_rebuild()
    else start_doc > 0
        Harness->>Harness: seed_corpus(start_doc)
    end
    loop documents from start_doc to docs
        Harness->>Store: index document chunks
        Store->>DB: replace existing chunks
    end
    Harness->>Store: finish_full_rebuild()
    Harness->>Store: load_from_db()
    Store->>DB: count_chunks()
    DB-->>Harness: actual chunk count
    Harness->>Harness: write report with indexed_chunks
    Harness-->>CI: contention assertion result
Loading

性能规模 CI 断言与 artifact 保留流程图

flowchart TD
    A[workflow_dispatch or weekly schedule] --> B[Run perf_scale with 50k defaults]
    B --> C{contention_factor <= max limit?}
    C -->|Yes| D[Process succeeds]
    C -->|No| E[Process exits nonzero]
    D --> F[Upload perf_scale_ci_report.json]
    E --> F
    F --> G[Artifact available for PASS or FAIL run]
Loading

文件级变更

变更 详细信息 文件
新增可持续运行、可调参且带性能断言的 50k 规模压测 CI workflow,并确保失败时保留报告 artifact。
  • 支持手动参数与每周定时运行,默认执行 50k 文档压测。
  • 以并发/顺序 P50 争用系数作为可配置阈值,超标使 job 失败。
  • 设置长超时、并发排队策略、Rust 缓存与报告 artifact 上传。
.github/workflows/perf-scale.yml
扩展压测 harness,支持断点续跑和基于数据库真实状态的准确计数。
  • 新增 --start-doc 续跑参数,续跑时保留数据库并从指定文档继续写入。
  • 新增 --max-contention-factor 参数,在报告写盘后执行 CI 断言。
  • 用数据库实际 chunk 数生成 indexed_chunks 与吞吐统计,避免重复覆盖导致虚报。
memori-core/examples/perf_scale.rs
补充 10k/50k 规模验证结果、CI 使用说明及性能边界结论。
  • 记录不同规模的延迟、吞吐与争用系数,并明确 doc_recall 是主要规模敏感项。
  • 说明 workflow 触发方式、默认参数、断言规则和 artifact 格式。
docs/qa/PERF_SCALE_50K.md
同步项目成熟度说明与 1.5.2 发布文档,满足版本一致性检查。
  • 将 50k 压测从待实现移至已完成能力,并链接验证文档。
  • 新增 release notes 索引与 1.5.2 版本说明,涵盖压测 harness 和 CI 修复。
README.md
docs/README.md
docs/release/RELEASE_NOTES_v1.5.2.md

提示与命令

与 Sourcery 交互

  • 触发新的审查: 在 pull request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 从审查评论生成 GitHub issue: 回复审查评论,请 Sourcery 根据该评论创建 issue。你也可以回复 @sourcery-ai issue,从该评论创建 issue。
  • 生成 pull request 标题: 在 pull request 标题的任意位置写入 @sourcery-ai,即可随时生成标题。你也可以在 pull request 中评论 @sourcery-ai title,随时重新生成标题。
  • 生成 pull request 摘要: 在 pull request 正文中任意位置写入 @sourcery-ai summary,即可在指定位置随时生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary,随时重新生成摘要。
  • 生成审查者指南: 在 pull request 中评论 @sourcery-ai guide,即可随时重新生成审查者指南。
  • 解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve,即可解决所有 Sourcery 评论。如果你已经处理完所有评论且不想再看到它们,这一功能会很有用。
  • 忽略所有 Sourcery 审查: 在 pull request 中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 审查。如果你想从新的审查开始,这一功能尤其有用——别忘了评论 @sourcery-ai review 以触发新的审查!

自定义使用体验

访问你的控制面板

  • 启用或禁用审查功能,例如 Sourcery 生成的 pull request 摘要、审查者指南等。
  • 更改审查语言。
  • 添加、删除或编辑自定义审查说明。
  • 调整其他审查设置。

获取帮助

Original review guide in English

Reviewer's Guide

本 PR 建立了可手动或定时复跑的 50k 压测 CI,并在 harness 中加入断点续跑、真实 chunk 计数和争用系数断言;同时修复失败时报告 artifact 丢失问题,补充规模验证文档及 1.5.2 release notes 以完成文档和版本一致性。

Sequence diagram for resumable perf-scale indexing and reporting

sequenceDiagram
    participant CI as PerfScaleCI
    participant Harness as perf_scale
    participant Store as VectorStore
    participant DB as SQLiteDB

    CI->>Harness: Run with --start-doc and --report
    alt start_doc == 0
        Harness->>Store: purge_all_index_data()
        Harness->>Store: begin_full_rebuild()
    else start_doc > 0
        Harness->>Harness: seed_corpus(start_doc)
    end
    loop documents from start_doc to docs
        Harness->>Store: index document chunks
        Store->>DB: replace existing chunks
    end
    Harness->>Store: finish_full_rebuild()
    Harness->>Store: load_from_db()
    Store->>DB: count_chunks()
    DB-->>Harness: actual chunk count
    Harness->>Harness: write report with indexed_chunks
    Harness-->>CI: contention assertion result
Loading

Flow diagram for perf-scale CI assertions and artifact preservation

flowchart TD
    A[workflow_dispatch or weekly schedule] --> B[Run perf_scale with 50k defaults]
    B --> C{contention_factor <= max limit?}
    C -->|Yes| D[Process succeeds]
    C -->|No| E[Process exits nonzero]
    D --> F[Upload perf_scale_ci_report.json]
    E --> F
    F --> G[Artifact available for PASS or FAIL run]
Loading

File-Level Changes

Change Details Files
新增可持续运行、可调参且带性能断言的 50k 规模压测 CI workflow,并确保失败时保留报告 artifact。
  • 支持手动参数与每周定时运行,默认执行 50k 文档压测。
  • 以并发/顺序 P50 争用系数作为可配置阈值,超标使 job 失败。
  • 设置长超时、并发排队策略、Rust 缓存与报告 artifact 上传。
.github/workflows/perf-scale.yml
扩展压测 harness,支持断点续跑和基于数据库真实状态的准确计数。
  • 新增 --start-doc 续跑参数,续跑时保留数据库并从指定文档继续写入。
  • 新增 --max-contention-factor 参数,在报告写盘后执行 CI 断言。
  • 用数据库实际 chunk 数生成 indexed_chunks 与吞吐统计,避免重复覆盖导致虚报。
memori-core/examples/perf_scale.rs
补充 10k/50k 规模验证结果、CI 使用说明及性能边界结论。
  • 记录不同规模的延迟、吞吐与争用系数,并明确 doc_recall 是主要规模敏感项。
  • 说明 workflow 触发方式、默认参数、断言规则和 artifact 格式。
docs/qa/PERF_SCALE_50K.md
同步项目成熟度说明与 1.5.2 发布文档,满足版本一致性检查。
  • 将 50k 压测从待实现移至已完成能力,并链接验证文档。
  • 新增 release notes 索引与 1.5.2 版本说明,涵盖压测 harness 和 CI 修复。
README.md
docs/README.md
docs/release/RELEASE_NOTES_v1.5.2.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

您好——我发现了 1 个问题

面向 AI Agent 的提示
请处理此次代码审查中的评论:

## 各条评论

### 评论 1
<location path="memori-core/examples/perf_scale.rs" line_range="195-197" />
<code_context>
-    // 干净起点:删除旧 DB。
-    let _ = std::fs::remove_file(&args.db_path);
+    // 干净起点:删除旧 DB(--start-doc>0 续跑时保留)。
+    if args.start_doc == 0 {
+        let _ = std::fs::remove_file(&args.db_path);
+    }
     if let Some(parent) = args.db_path.parent() {
         std::fs::create_dir_all(parent)?;
</code_context>
<issue_to_address>
**问题 (bug_risk):**`--start-doc` 大于零,但指定的数据库不存在时,代码会创建一个新的空数据库,并且只为 `start_doc..docs` 范围内的文档建立数据;此时,报告却声称包含完整的 `docs` 文档集,尽管前面的文档并不存在。

**触发条件:** 使用缺失、已删除或指定错误的 `--db-path` 开始续跑时。

**建议修复:** 除非数据库存在且包含预期的既有文档集,否则应立即失败;或者在继续之前,显式地为缺失的前缀文档建立数据。
</issue_to_address>

Sourcery 评估

等待批准。 需要先处理 1 个发现的问题。

阻塞性发现:memori-core/examples/perf_scale.rs:197


Sourcery 对开源项目免费——如果您喜欢我们的审查,请考虑分享给他人 ✨
Original comment in English

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="memori-core/examples/perf_scale.rs" line_range="195-197" />
<code_context>
-    // 干净起点:删除旧 DB。
-    let _ = std::fs::remove_file(&args.db_path);
+    // 干净起点:删除旧 DB(--start-doc>0 续跑时保留)。
+    if args.start_doc == 0 {
+        let _ = std::fs::remove_file(&args.db_path);
+    }
     if let Some(parent) = args.db_path.parent() {
         std::fs::create_dir_all(parent)?;
</code_context>
<issue_to_address>
**issue (bug_risk):** When `--start-doc` is greater than zero but the specified database does not already exist, the code creates a new empty database and seeds only documents in `start_doc..docs`; the report then claims the full `docs` corpus even though the earlier documents are absent.

**Triggers:** When a resume is started with a missing, deleted, or incorrectly specified `--db-path`.

**Suggested fix:** Fail fast unless the database exists and contains the expected prior corpus, or explicitly seed the missing prefix before continuing.
</issue_to_address>

Sourcery assessment

Approval pending. 1 finding to address first.

Blocking findings: memori-core/examples/perf_scale.rs:197


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment on lines +195 to +197
if args.start_doc == 0 {
let _ = std::fs::remove_file(&args.db_path);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

问题 (bug_risk):--start-doc 大于零,但指定的数据库不存在时,代码会创建一个新的空数据库,并且只为 start_doc..docs 范围内的文档建立数据;此时,报告却声称包含完整的 docs 文档集,尽管前面的文档并不存在。

触发条件: 使用缺失、已删除或指定错误的 --db-path 开始续跑时。

建议修复: 除非数据库存在且包含预期的既有文档集,否则应立即失败;或者在继续之前,显式地为缺失的前缀文档建立数据。

Original comment in English

issue (bug_risk): When --start-doc is greater than zero but the specified database does not already exist, the code creates a new empty database and seeds only documents in start_doc..docs; the report then claims the full docs corpus even though the earlier documents are absent.

Triggers: When a resume is started with a missing, deleted, or incorrectly specified --db-path.

Suggested fix: Fail fast unless the database exists and contains the expected prior corpus, or explicitly seed the missing prefix before continuing.

@FPSZ

FPSZ commented Sep 15, 2026

Copy link
Copy Markdown
Owner

审过了,可以合。上一轮指出的两条都修对了,也都核实过:

  • if: always()perf-scale.yml:68)—— 加上了,注释也写明了理由(断言 FAIL 时才最需要看报告)。if-no-files-found: error 这个搭配也对。
  • resume 重复计数perf_scale.rs:416)—— 改成以 DB 里的真实 chunk 数为最终值,--start-doc 小于实际进度时不会再虚报 indexed_chunks 和 chunks/s。注释把原因写清楚了。

其余部分(workflow 的手动输入 + 周期触发、--max-contention-factor 断言、文档里 10k/50k 结果)看下来没问题。

唯一一件事:请把 docs/release/RELEASE_NOTES_v1.5.2.mddocs/README.md 那 2 行从这个 PR 摘掉。

这份 release notes 在 #2 / #3 / #4 里完全相同(md5 一致),且写了 "adds OCR ingestion for images and scanned documents"。#4 的 OCR 还在返工(漏了间接 /Resources / /XObject,多数真实扫描件索引不到),先合这个 PR 会让仓库发布一份与实际不符的说明。建议 release notes 统一留在 #4

摘掉之后就可以合了。

该 release notes 在 FPSZ#2/FPSZ#3/FPSZ#4 三份 PR 中内容相同,且写明 adds OCR ingestion;若本 PR 先合,仓库会发布与事实不符的说明。按评审统一只保留在 OCR PR。docs/README.md 的两行索引同理一并摘除。
wjs480 pushed a commit to wjs480/Memori-Vault that referenced this pull request Sep 15, 2026
该 release notes 在 FPSZ#2/FPSZ#3/FPSZ#4 三份 PR 中内容相同,且写明 adds OCR ingestion;若本 PR 先合,仓库会发布与事实不符的说明。按评审统一只保留在 OCR PR。docs/README.md 的两行索引同理一并摘除。
@FPSZ

FPSZ commented Sep 16, 2026

Copy link
Copy Markdown
Owner

复审通过,可以合了

RELEASE_NOTES_v1.5.2.mddocs/README.md 已从本 PR 摘出,现在只剩压测相关的 4 个文件,职责干净。

前一轮的两条修复维持不变,再确认一次:

  • perf-scale.yml:68if: always() —— 断言 FAIL 时报告不再丢失
  • perf_scale.rs 以 DB 真实 chunk 数为最终值 —— resume 时 --start-doc 低于实际进度不再重复计数

无新增意见。

@FPSZ
FPSZ merged commit 01585f5 into FPSZ:collab Sep 16, 2026
1 check passed
FPSZ added a commit to wjs480/Memori-Vault that referenced this pull request Sep 16, 2026
合并 FPSZ#2/FPSZ#3/FPSZ#5 后的 collab,三处冲突均为双方各自新增内容,保留双方:
- README.md「已实现但仍在优化」:50k 压测条目 + OCR 条目
- docs/qa/RETRIEVAL_BASELINE_V2.md:作答层 LLM-judge 基线 + OCR 接入与边界
- memori-server/src/dto.rs:AppSettings 的 index_filter 与 ocr_tesseract_path 两个字段

同时启用 pdf_with_indirect_resources_is_extracted(原 #[ignore]):
手工构造 lopdf::Stream 用结构体字面量会绕过 /Length 写入(lopdf object.rs:602
的 Stream::new 才会 dict.set("Length", ...)),存盘后流长度为 0、load 回来
content 为空,解码拿不到像素,测试因此假失败——与 get_pages() 无关(实测
get_pages()=1、get_page_resources 也正确返回 inherited)。改用 Stream::new 后
测试通过,可作为间接 /Resources + 间接 /XObject 的回归锁。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants