SeqnosByKey_Bucketed writes an empty file per key for every bucket since seqno 0
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- cpp
- Lĩnh vực
- databases, performance
Hướng nghiên cứu
Start with src/indexing/strategies/seqnos_by_key_bucketed.cpp, especially visit_entry, store_empty_buckets, query_bucket, and current_results; the issue links directly to these sections. Trace how missing buckets are distinguished from empty ones and how queries use current_results. Done means sparse keys no longer generate or fetch empty buckets, queries still detect lost data correctly, and per-key memory use is bounded; the issue presents design ideas but leaves the approach open.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Describe the bug
SeqnosByKey_Bucketed stores a file per key for every bucket from seqno 0 up to the key's current bucket, including empty ones:
- The first time it sees a key at seqno S, it stores an empty bucket for every bucket before S (visit_entry, store_empty_buckets). With 1,000 seqnos per bucket, a key first written at seqno 5,000,000 costs 5,000 files.
- When a key is written again after a gap, it stores an empty bucket for every bucket in the gap (L384-L388).
So the index costs about keys × seqno / bucket size files, however few writes each key has. The empty files are needed today because a query treats a missing bucket as lost data and re-indexes from seqno 0 (L254-L283).
Separately, current_results keeps an entry for every key ever indexed and never frees it (L24-L26). Queries depend on that, since a key without an entry is treated as never written (L311-L322), so entries can't just be evicted.
Each node builds all of this on its own, and again after every restart, because .index is wiped on start (enclave_lfs_access.h#L295-L302).
We use two LazyStrategy<SeqnosByKey_Bucketed<...>> indexes (1,000 seqnos per bucket, 200 buckets) keyed by collection and by (collection, tag) and we see the following:
- In a 3-node sandbox on 7.0.23, building the index at keys × seqno ≈ 1.6e9 wrote 789k files: 3.3 GB on disk (about 4.2 KB each). Node RSS went up about 323 MiB and didn't come back after the build. We didn't dig into the RSS part. The LFS keeps no per-file state, so it may be the queued async writes plus allocator retention.
- On one production instance, CCF logged 182k
Writing LFS fileoperations slower than 10 ms over three weeks, up to 4.3 s each. All of them were 108-116 byte files, so empty or single-entry buckets. - Range queries on sparse keys also fetch every empty bucket in the range, which churns the shared bucket LRU.
To Reproduce
A standalone harness that calls visit_entry and get_write_txs_impl on the real strategy (main at 00d0976e7, 1,000 seqnos per bucket, 200 buckets), with an in-memory LFS that counts store() calls:
- Key A first written at seqno 1: no files.
- Key B first written at seqno 1,000,000: 1,000 files, all empty.
- Key A written again at seqno 2,000,000: 2,000 files (1 with data, 1,999 empty).
- 100 new keys first written around seqno 5,000,000: 500,000 empty files.
- A query for B over the 198,000 seqnos before its first write: 198 bucket fetches, all empty.
- 200,000 distinct keys: 200,000
current_resultsentries (about 160 B each with 21-byte keys), still there after later writes move the watermark on. - With an LFS that drops empty buckets, the next query on a range in the gap resets the watermark to 0 and clears every key.
Happy to share the harness used for checking this.
Expected behavior
Index cost should grow with the number of writes, not with keys × ledger length, and per-key memory should be bounded. A couple of ideas, but you know this code better:
- Don't store empty buckets. Have each stored bucket, and the in-memory current one, record the start of the key's previous non-empty bucket, so a query can tell an empty bucket from a lost file and only fetches buckets with data.
- Flush and drop
current_resultsentries for keys that haven't been written for a while, keeping a small marker on disk so queries still know the key exists.
Environment information
CCF 7.0.23. The code is unchanged on main at 00d0976e71afc0613328225e6f4074a78f52a592.
Additional context
An app can't bound this index by key count alone, since a key created late in a ledger's life costs seqno / bucket size files. The workaround we're looking at is turning the index off above a keys × seqno threshold, but that makes range queries on exactly those ledgers about 2x slower.
- Ngôn ngữ chính
- C++
- Star
- 876
- Fork
- 264
- Merge trung bình
- 1 ngày 16 giờ
- Pull request đã merge (30 ngày)
- 127
Chuẩn bị môi trường
Khởi chạy dev container của dự án ngay trên trình duyệt, bằng tài khoản GitHub của bạn.
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của microsoft/CCF
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
microsoft/CCF#8688 · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 8/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Make stderr output exclusive to fatal paths and consistent across all fatal pathsCó thể đã có người làm @achamayou đã nhận 2 ngày trước. Đang mở
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
Maintainer thường phản hồi trong vòng 1 ngày
-
raft.h hardeningĐang mở
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
microsoft/CCF#8606 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của microsoft/CCF
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 77/100
arvidn/libtorrent#9149 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Niko1221/Strata#5560 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 4 ngày
-
NVIDIA windows
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 1 ngày
-
[辞書] C/C++のプリプロセッサ指令名を英字のままにするĐang mở要トリアージ 辞書
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 86/100
yksr-melt/Meltype#1625 · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày