Skip to content

refactor(fibre): replace go-ds-pebble wrapper with direct Pebble API#7062

Merged
walldiss merged 3 commits intomainfrom
refactor/fibre-store-direct-pebble
Apr 14, 2026
Merged

refactor(fibre): replace go-ds-pebble wrapper with direct Pebble API#7062
walldiss merged 3 commits intomainfrom
refactor/fibre-store-direct-pebble

Conversation

@walldiss
Copy link
Copy Markdown
Member

@walldiss walldiss commented Apr 13, 2026

Summary

Replaces the go-ds-pebble / go-datastore abstraction layer with direct Pebble v2 API calls.

Motivation

The go-datastore interface adds overhead through interface indirection, key conversion (ds.Key → bytes), and extra allocations. Local benchmarks comparing wrapper vs direct Pebble on the same workload:

Read path (prefix scan for shard retrieval):

  • 2.3x faster (207 µs → 90 µs)
  • 3x fewer allocations (27 → 9 allocs/op)
  • 3x less memory (1.2 MB → 403 KB per read)
  • The go-datastore Query interface builds result channels and copies values into generic result structs

Write path (batch write of promise + shard + prune key):

  • ~10-15% faster under concurrent load (noisy, dominated by Pebble internals)
  • Modest allocation reduction (30 → 26 allocs/op at c=50)

The store only uses basic operations (batch write, point lookup, prefix scan, range delete) that map directly to Pebble's native API. The abstraction layer provides no benefit since there is no backend swapping.

Changes

  • Removed imports: go-datastore, go-ds-pebble, go-ds-badger4
  • Store struct: ds.Batching*pebbledb.DB
  • All methods rewritten to use native Pebble API (Batch.Set, DB.Get, DB.NewIter, etc.)
  • NewBadgerStore removed (was unused alias)
  • NewMemoryStore uses in-memory Pebble via vfs.NewMem()
  • Added iter.Error() checks after iterator loops

Test plan

  • All store tests pass
  • Full ./fibre/... test suite passes
  • CI passes

Closes https://linear.app/celestia/issue/PROTOCO-1495

🤖 Generated with Claude Code

CPU profiling showed the go-ds-pebble wrapper adds ~45% overhead to
every store write due to interface indirection through ds.Batching,
key conversion from ds.Key to bytes, and extra allocations. The store
only uses basic operations (Put, Get, prefix scan, batch delete) that
map directly to Pebble's native API.

- Store struct: ds.Batching -> *pebbledb.DB
- NewMemoryStore: pebbledb.Open with vfs.NewMem()
- NewBadgerStore: delegates to NewPebbleStore (kept for test compat)
- NewPebbleStore: pebbledb.Open directly (all tuning options preserved)
- Put: db.NewBatch + batch.Set + batch.Commit
- Get: prefix scan via pebbledb.NewIter with LowerBound/UpperBound
- GetPaymentPromise: db.Get with closer pattern
- PruneBefore: iterator + batch delete
- Key functions return []byte instead of ds.Key
- Added prefixUpperBound helper for prefix scans
- Removed imports: go-datastore, go-datastore/query, go-datastore/sync,
  go-ds-badger4, go-ds-pebble

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@walldiss walldiss requested a review from a team as a code owner April 13, 2026 18:41
@walldiss walldiss requested review from evan-forbes and removed request for a team April 13, 2026 18:41
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

devin-ai-integration[bot]

This comment was marked as resolved.

@Wondertan
Copy link
Copy Markdown
Member

Measured: fibre server CPU dropped from ~200% to ~108% under the same single-encoder workload after this change.

To confirm, the impact was measured without value separation?

evan-forbes
evan-forbes previously approved these changes Apr 13, 2026
Copy link
Copy Markdown
Member

@evan-forbes evan-forbes left a comment

Choose a reason for hiding this comment

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

besides the linter failures seems gud

Comment thread fibre/store.go
Comment on lines -238 to +216
func (s *Store) PruneBefore(ctx context.Context, before time.Time) (int, error) {
results, err := s.ds.Query(ctx, query.Query{
Prefix: "/prune/",
KeysOnly: true,
Orders: []query.Order{query.OrderByKey{}},
func (s *Store) PruneBefore(_ context.Context, before time.Time) (int, error) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't have a strong opinion here but do we want to permanently remove the context?

Comment thread fibre/store.go Outdated
Add missing iter.Error() checks after Pebble iterator loops in Get and
PruneBefore to avoid silently converting storage errors into
ErrStoreNotFound or partial prunes. Replace []byte(fmt.Sprintf(...))
with fmt.Appendf(nil, ...) to satisfy the modernize linter. Remove
stale NewBadgerStore wrapper and unused ipfs dependencies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@walldiss walldiss added this pull request to the merge queue Apr 14, 2026
Merged via the queue into main with commit 5ff3719 Apr 14, 2026
32 checks passed
@walldiss walldiss deleted the refactor/fibre-store-direct-pebble branch April 14, 2026 15:12
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.

3 participants