Skip to content

feat(snapshot-log): add path history index provider - #7505

Merged
qin-ctx merged 7 commits into
volcengine:mainfrom
baojun-zhang:feat/snapshot-log-provider
Nov 13, 2026
Merged

qin-ctx merged 7 commits into
volcengine:mainfrom
baojun-zhang:feat/snapshot-log-provider

Conversation

@baojun-zhang

@baojun-zhang baojun-zhang commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Description

This PR adds SnapshotLog, a path history index for snapshot/log?paths=....

The slow case in #6750 comes from filtered snapshot log queries walking the
branch commit chain and checking the requested path commit by commit. SnapshotLog
keeps a derived account + branch + path -> commit index so file, directory,
and multi-path history queries can avoid scanning unrelated commits when the
index is current.

The Git object model remains the source of truth. SnapshotLog is only an
acceleration layer: if the index is missing, stale, too far behind, or cannot be
used for a path, the request falls back to the existing scan behavior.

Human Involvement

  • A human participated in the implementation or review loop
  • This PR was generated entirely by AI agents without human participation in the loop

Related Issue

Closes #6750

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement
  • Test update

Changes Made

  • Added the SnapshotLog store abstraction with SQLite and MySQL providers.
  • Wired filtered snapshot/log?paths=... queries to use SnapshotLog when the index is complete, with scan fallback when it is not.
  • Indexed successful commit() and restore() changes after branch ref CAS, using best-effort writes that do not fail the main operation.
  • Added background backfill triggers for missing, stale, or failed SnapshotLog writes.
  • Added SnapshotLog config under [git.snapshot_log], including provider = "none" to disable the acceleration layer.
  • Added focused tests for commit indexing, directory fan-out, tail merge, restore path prefixing, and stale latest handling.

Testing

  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have tested this on the following platforms:
    • Linux
    • macOS
    • Windows

Commands run:

cargo test -p ragfs --features snapshot_log snapshot_log
cargo check -p ragfs
PYO3_PYTHON=/Users/bytedance/project/OpenViking/.venv/bin/python cargo check -p ragfs-python
/Users/bytedance/project/OpenViking/.venv/bin/python -m py_compile openviking_cli/utils/config/git_config.py

Checklist

  • My code follows the project's coding style
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

Screenshots (if applicable)

N/A

Additional Notes

snapshot/log without paths still uses the existing global commit scan. That
query asks for branch history, not path history, so it should use a separate
branch commit index if it needs acceleration later.

Cargo output still contains existing repository warnings. They were not cleaned
up in this PR to keep the change focused.

Add SnapshotLog stores and wire filtered snapshot log queries to use the
path history index with scan-based fallback.
Propagate SnapshotLog config into the binding setup and preserve deleted
descendant history when files replace directories. Reduce backfill and
append overhead so indexing work does not add unnecessary object reads or
SQL round trips.
Always compile SnapshotLog with the git module and keep provider selection
as runtime configuration. Avoid extra tree reads when indexing is disabled
and reuse tail-scan results after concurrent head updates.
Route SnapshotLog settings through git.snapshot.log so future snapshot
settings can share the git.snapshot section.
@baojun-zhang

Copy link
Copy Markdown
Collaborator Author

SnapshotLog 性能测试

场景假设

  • commit 数:1000。
  • 文件数量:1000 个文件。
  • 查询条件:单文件路径 snapshot/log?paths=...。
  • 返回限制:limit = 20。
  • 文件路径深度:约 3,例如 workspace/d0/d0/f000.md。

Mock 数据构造

使用单 branch,连续生成 1000 个 commit。文件树固定为 10 * 10 * 10
结构,共 1000 个基础文件。不再区分 noise 和 target,每个文件都是普通测试文件。

workspace/
  d0/
    d0/
      f000.md
      f001.md
      ...
      f009.md
    d1/
      f010.md
      ...
      f019.md
    ...
    d9/
      ...
      f099.md
  d1/
    d0/
      f100.md
      ...
  ...
  d9/
    d9/
      f990.md
      ...
      f999.md

基础文件路径生成规则:

file_index = commit_index - 1
first_dir = file_index / 100
second_dir = (file_index / 10) % 10
base_path = workspace/d{first_dir}/d{second_dir}/f{file_index:03}.md

每个 commit 固定修改一个基础文件,保证 1000 commits 和 1000 files 的规模:

commit 1    -> workspace/d0/d0/f000.md
commit 2    -> workspace/d0/d0/f001.md
...
commit 1000 -> workspace/d9/d9/f999.md

每个 commit 再按命中分布规则额外修改固定的 case 文件。表格中的每一行是一个
独立 case,每个 case 固定查询自己的文件 path。不同 case 使用不同查询文件,
避免命中分布互相污染。

命中分布 查询文件 path 额外写入规则
最新 20 个 commit 全命中 workspace/d9/d9/f999.md commit 981..1000 额外修改该文件
每 10 个 commit 命中 1 个 workspace/d8/d0/f800.md commit_index % 10 == 0 时额外修改该文件
每 50 个 commit 命中 1 个 workspace/d7/d0/f700.md commit_index % 50 == 0 时额外修改该文件
只在最老 20 个 commit 命中 workspace/d0/d0/f000.md commit 1..20 额外修改该文件
1000 个 commit 里只命中 5 个 workspace/d5/d0/f500.md commit 1, 250, 500, 750, 1000 额外修改该文件
1000 个 commit 无命中 workspace/d6/d0/f600.md 不额外修改该文件

以 workspace/d8/d0/f800.md 为例,SnapshotLog fan-out 后应覆盖:

workspace/d8/d0/f800.md
workspace/d8/d0
workspace/d8
workspace
/

这套数据主要测试单文件 path 查询,同时保留祖先路径索引:

snapshot/log?paths=workspace/d8/d0/f800.md&limit=20

注意:这些 case 文件也属于基础文件树。基础写入可能会让它们额外命中一次。
测试脚本如果要严格命中表格,应让 base_path 生成时跳过这些 case 文件。

1000 commits 测试记录

命中分布 本地现状耗时 NAS 现状耗时 SnapshotLog 耗时 对比本地提升 对比 NAS 提升
最新 20 个 commit 全命中 27.61 ms 503.38 ms 6.38 ms 4.3x 78.9x
每 10 个 commit 命中 1 个 233.63 ms 3476.86 ms 6.25 ms 37.4x 556.3x
每 50 个 commit 命中 1 个 1024.15 ms 15651.17 ms 6.32 ms 162.1x 2476.5x
只在最老 20 个 commit 命中 1202.46 ms 13660.51 ms 6.04 ms 199.2x 2261.7x
1000 个 commit 里只命中 5 个 1109.66 ms 14933.65 ms 4.15 ms 267.5x 3598.5x
1000 个 commit 无命中 733.26 ms 11818.25 ms 3.29 ms 223.2x 3592.2x

测试口径:

  • 本地现状:provider = none,每个 case 预热后执行 100 次,记录平均耗时。
  • NAS 现状:provider = none,同版本 NAS 环境,每个 case 预热后执行 100 次,
    记录平均耗时。
  • SnapshotLog:SQLite 索引 warm up 完成后,每个 case 执行 100 次,记录平均耗时。
  • 对比本地提升:本地现状耗时 / SnapshotLog 耗时。
  • 对比 NAS 提升:NAS 现状耗时 / SnapshotLog 耗时。

结论

SnapshotLog 对 snapshot/log?paths=单文件 的收益成立。SQLite 索引 warm up
完成后,6 个 case 的耗时稳定在 3.29 ms ~ 6.38 ms。

对比本地现状,SnapshotLog 的提升范围为 4.3x ~ 267.5x。最新 20 个 commit
全命中时提升 4.3x;命中分布变稀疏或靠近历史末端时,提升达到
162.1x ~ 267.5x。

对比 NAS 现状,SnapshotLog 的提升范围为 78.9x ~ 3598.5x。稀疏命中和
无命中场景提升最明显,达到 2261.7x ~ 3598.5x。

性能差异来自旧逻辑需要倒扫 commit 链,并反复读取 tree 做 path 判断。NAS 会
进一步放大量小对象读取的延迟。SnapshotLog 将查询变成按 path 查索引,再读取
少量命中 commit,因此深历史单文件查询能从秒级降到毫秒级。

@qin-ctx qin-ctx left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

路径历史索引能解决实际的查询延迟问题,本地对照也确认了对象读取次数明显减少,方案有合入价值。

当前建议 REQUEST_CHANGES:合并前需要解决 Windows 默认配置无法启动、独立工作区共用默认索引导致反复扫描历史,以及索引数据库故障阻断服务启动这三个问题。另有一条非阻塞问题:补齐索引后,目录历史会漏掉空目录的删除记录。具体场景和依据见行内评论。

Comment thread crates/ragfs-python/src/git.rs Resolved
Use a workspace-scoped SQLite default when no explicit path is set.
Fall back to Git scanning when a SnapshotLog store is unavailable.

@qin-ctx qin-ctx left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

已重新评审当前完整改动。按路径查询历史的性能收益成立,方案值得合入。上一轮关于 Windows 路径、默认索引库的工作区隔离,以及索引数据库故障阻断启动的三个阻塞问题,当前修改均已解决。

本轮没有发现新的阻塞问题,补充两条非阻塞意见:直接使用原生绑定时的旧配置兼容问题,以及索引落后超过扫描上限时无法由查询触发补齐的问题。具体场景和验证结果见行内评论。

验证包括 196 个 Git 相关 Rust 测试,以及真实 SQLite、MySQL 8.4 和原生绑定的运行对照。文件、目录、多路径查询,以及多客户端写入、并发补齐和快照恢复的结果均与原扫描逻辑一致。

Comment thread crates/ragfs-python/src/git.rs Resolved
Comment thread crates/ragfs/src/git/service/log.rs Resolved
@qin-ctx
qin-ctx merged commit bd70f20 into volcengine:main Nov 13, 2026
20 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in OpenViking project Nov 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Bug]: snapshot/log 按路径查询历史版本耗时 5~10 秒,Studio 版本历史加载缓慢

2 participants