GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — PK optimizations by blp · Pull Request #5314 · feldera/feldera

Conversation

@blp

@blp blp commented Dec 18, 2025

Copy link
Copy Markdown
Member

This PR implements two optimizations to indexed Z-set storage.

The first, which is implemented in the final commit, is mostly above the level of the storage file implementation. It is a change to the indexed Z set implementation. In this optimization, if a key K has fewer than a threshold number of (V,R) pairs (or perhaps less than a threshold number of bytes of (V,R) pairs), then we write those (V,R) pairs as auxdata in column 0. Then we avoid any reads to column 1 at all for visiting those keys and their values.

The only change needed to the storage file implementation for this is to allow a key in column 0 to have zero values in column 1 (currently this will panic), which is implemented in the second-to-last commit.

The second, implemented by the third commit, is at the level of the storage file implementation. There is some confusion here about what we really have in column 1. It is essentially a btree over 2-tuples (R,K), where R is the row number in column 1. Each row in column 0 includes an accompanying range of column-1 row numbers for its values, so R allows that range to be looked up. K is the key for column 1, which for an indexed Z-set is the V from each (K,V,R) tuple. Storing it in the b-tree allows efficient searching by value, which is something that the DBSP cursor supports.

However, when there's only one column-1 value for each column-0 key, putting the column-1 values in the b-tree don't help. That means that we can essentially reduce that b-tree's keys from 2-tuples (R,K) into just R.

(Note that R isn't stored on a per-row basis even now, we use a much more efficient representation, since it's just a count.)

Storage format compatibility

With this PR, Feldera can read storage written by earlier versions, but storage written after this PR cannot be read by earlier versions of Feldera.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@blp
blp requested review from gz and ryzhyk December 18, 2025 20:34
@blp blp self-assigned this Dec 18, 2025
Copilot AI review requested due to automatic review settings December 18, 2025 20:34
@blp blp added DBSP core Related to the core DBSP library performance storage Persistence for internal state in DBSP operators rust Pull requests that update Rust code labels Dec 18, 2025

This comment was marked as resolved.

Sign in to view

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@blp
blp force-pushed the pk-optimizations branch from d63901f to b75273c Compare December 18, 2025 21:07
@blp
blp temporarily deployed to ci December 18, 2025 21:38 — with GitHub Actions Inactive
@blp
blp temporarily deployed to ci December 18, 2025 23:26 — with GitHub Actions Inactive
@blp

blp commented Dec 19, 2025

Copy link
Copy Markdown
Member Author

In fact I see that clippy agrees, it appended a commit that changes some pieces of code to use if-let chains.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@blp
blp force-pushed the pk-optimizations branch from b75273c to cb780ff Compare December 23, 2025 17:42
@blp

blp commented Dec 23, 2025

Copy link
Copy Markdown
Member Author

I pushed a revision that adds metrics for the optimizations that this PR introduces, so that one can tell whether it should be a performance benefit.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@blp
blp temporarily deployed to ci December 23, 2025 20:07 — with GitHub Actions Inactive
@blp
blp temporarily deployed to ci December 23, 2025 23:14 — with GitHub Actions Inactive
@blp
blp force-pushed the pk-optimizations branch from cb780ff to 968824b Compare December 24, 2025 19:32
blp added 6 commits December 24, 2025 11:32
@blp
[dbsp] Drop unused opt_key_factory from IndexedWSetBatchFactories.
665d40a
Signed-off-by: Ben Pfaff <[email protected]>
@blp
[dbsp] Make storage file writer use generics.
9bfa7db
Until now, in dbsp::storage::file::writer, the ColumnWriter,
DataBlockBuilder, and IndexBlockBuilder haven't needed to be parameterized
by their key or auxdata types.  An upcoming commit will need that, so this
commit prepares for it by parameterizing them.

This shouldn't affect the storage format.

Signed-off-by: Ben Pfaff <[email protected]>
@blp
[dbsp] Omit unneeded index bounds in storage layer files when not nee…
82f2af9
…ded.

Columns 1 (and greater) in a layer file are essentially B-trees over tuples
(R,K), where R is the row number and K is the key.  Each row in column 0
includes as auxiliary data a range R0..R1 of rows in column 1 (the "row
group"), so R in the B-tree allows that range to be looked up.  Storing
the minimum and maximum keys of child blocks in the index allows efficient
lookup of keys in row groups that span multiple data blocks.

However, when a row group starts at the beginning of a data block, there's
little value in including that key in its index block, because it won't
usually help us to avoid reading the data block.  It only helps if we're
searching for a key less than the minimum, which is rarely the case; more
often, we're iterating through the keys, and usually we're doing nested
iteration through the column-0 keys too, so that we'd typically have to
read the data block for another one of those anyhow.

Similarly, when a row group ends at the end of a data block, there's little
value in including its last key in the index block.

This can be a significant optimization when keys in column 1 are large.

In layer files where each row in column 0 has exactly one row in column 1,
this optimization means that the column-0 index will have no bounds at all.
Other layer files will benefit less.

Signed-off-by: Ben Pfaff <[email protected]>
@blp
[dbsp] Allow empty row groups in layer files.
f00cdaf
Until now, any row in column 0 had to have at least one row in column 1.
This commit allows there to instead be none.

Signed-off-by: Ben Pfaff <[email protected]>
@blp
[dbsp] Inline up to two values in FileIndexedZSet.
2260ad4
Indexed Z-sets are commonly used for updating indexes on primary keys.
For this purpose, each key usually has one value (for insertions and
deletions) or two values (for updates).  Writing this small number of
values to a second column maintained separately in the layer file causes
I/O to additional data blocks.

This commit introduces a new way to store these indexed Z-sets.  With
this commit, when a key has just one or two values, those values are
written inline with the key, which reduces the number of data blocks
that need to be fetched to read a key along with its values.  This
should improve performance.

This commit does drop two performance-oriented features from
FileIndexedZSet: push_cursor() and fetch().  I don't think that either
of these have really been used without explicit enabling via DevTweaks.
If they prove important, then we can figure out how to re-implement
them with the new format.

Signed-off-by: Ben Pfaff <[email protected]>
@blp
[dbsp] Add circuit profile metadata.
3ed076d
Add circuit profile metadata for inlined values and omitted bounds.

Signed-off-by: Ben Pfaff <[email protected]>
@blp
blp force-pushed the pk-optimizations branch from 968824b to 3ed076d Compare December 24, 2025 19:32
@blp

blp commented Dec 24, 2025

Copy link
Copy Markdown
Member Author

I pushed a revision that adds the metrics to the circuit profile instead. Probably a better fit there (thanks @ryzhyk for the suggestion).

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@feldera-bot
[ci] apply automatic fixes
91d53cb
Signed-off-by: feldera-bot <[email protected]>
@gz gz added the marketing Relevant for marketing content label Jan 20, 2026
@mihaibudiu

mihaibudiu commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

This PR seems to have developed conflicts.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

mythical-fred
mythical-fred suggested changes Feb 27, 2026
View reviewed changes

@mythical-fred mythical-fred left a comment

Copy link
Copy Markdown

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Four dbg!(column_info) calls left in storage/file/test.rs (lines 567, 633, 803, 860). These will spam stderr on every test run.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread crates/dbsp/src/storage/file/test.rs

let reader = layer_file.into_reader().unwrap();
let (reader, column_info) = layer_file.into_reader().unwrap();
dbg!(column_info);

@mythical-fred mythical-fred Feb 27, 2026

Copy link
Copy Markdown

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Four dbg!() calls left in this file (here + lines 633, 803, 860). Remove before merge — they'll pollute CI output on every test run.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@blp blp Feb 27, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

No, that's wrong, they'll only show up if a test fails.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@mythical-fred mythical-fred Feb 27, 2026

Copy link
Copy Markdown

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Fair point that cargo test captures stderr by default and only shows it on failure. But dbg!() is a temporary debugging macro — it executes on every test run (allocating, formatting, and printing), just silently. The right tool for persistent diagnostic output is tracing::debug!() or eprintln! with a descriptive comment. I'd still ask that these be removed before merge.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
mythical-fred
mythical-fred approved these changes Feb 27, 2026
View reviewed changes

@mythical-fred mythical-fred left a comment

Copy link
Copy Markdown

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Withdrawing the previous REQUEST_CHANGES — Gerd clarified that dbg!/eprintln! in test code is acceptable. LGTM.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
gz added a commit that referenced this pull request Nov 10, 2026
@gz
[build] Build on the validated AWS-LC FIPS 3.1.0 module.
7f512af
aws-lc-rs 1.18 pulls AWS-LC 4, which is still in comment resolution at the CMVP. aws-lc-rs 1.17.1 ships aws-lc-fips-sys 0.13.11, the crate that bundles AWS-LC FIPS 3.1.0 (certificates #5314 static, #5298 dynamic), so the lock pins both.

rustls 0.23.46, rustls-webpki 0.103.16 and async-nats 0.51.0 require aws-lc-rs 1.18 only for ML-DSA, which 1.17.1 exposes only as unstable. The patch section takes them from feldera's forks, which keep every upstream fix and gate ML-DSA behind a feature that stays off. rustls-webpki moves from 0.103.15 to 0.103.16, which rejects certificate paths through the distrusted emSign intermediates (RUSTSEC-2026-0382).

Signed-off-by: Gerd Zellweger <[email protected]>
gz added a commit that referenced this pull request Nov 10, 2026
@gz
[build] Build on the validated AWS-LC FIPS 3.1.0 module.
f915bca
aws-lc-rs 1.18 pulls AWS-LC 4, which is still in comment resolution at the CMVP. aws-lc-rs 1.17.1 ships aws-lc-fips-sys 0.13.11, the crate that bundles AWS-LC FIPS 3.1.0 (certificates #5314 static, #5298 dynamic), so the lock pins both.

rustls 0.23.46, rustls-webpki 0.103.16 and async-nats 0.51.0 require aws-lc-rs 1.18 only for ML-DSA, which 1.17.1 exposes only as unstable. The patch section takes them from feldera's forks, which keep every upstream fix and gate ML-DSA behind a feature that stays off. rustls-webpki moves from 0.103.15 to 0.103.16, which rejects certificate paths through the distrusted emSign intermediates (RUSTSEC-2026-0382).

Signed-off-by: Gerd Zellweger <[email protected]>

This branch was previously deployed

1 inactive (outdated) deployment
ci — cb780ff9 Deployed Dec 23, 2025 by blp via Publish Crates (Dry Run) / deploy #19896
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

Copilot code review Copilot
Copilot review effort
Applies to this pull request for everyone.Learn more about Copilot code review.
Copilot left review comments
@gz gz Awaiting requested review from gz
@ryzhyk ryzhyk Awaiting requested review from ryzhyk
+1 more reviewer
@mythical-fred mythical-fred mythical-fred approved these changes
Reviewers whose approvals may not affect merge requirements

At least 1 approving review is required to merge this pull request.

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@blp blp

Labels

DBSP core Related to the core DBSP library marketing Relevant for marketing content performance rust Pull requests that update Rust code storage Persistence for internal state in DBSP operators

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

6 participants

@blp @mihaibudiu @mythical-fred @gz @feldera-bot
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.