Skip to content

Adopt upstream DataFusion 54 + size-cap patch#7

Merged
anoop-narang merged 14 commits into
mainfrom
adopt-datafusion-54
Jul 3, 2026
Merged

Adopt upstream DataFusion 54 + size-cap patch#7
anoop-narang merged 14 commits into
mainfrom
adopt-datafusion-54

Conversation

@anoop-narang

Copy link
Copy Markdown
Collaborator

Brings the fork's main up to upstream XiangpengHao/liquid-cache@746d639 (DataFusion 54) and re-applies the single hotdata patch on top.

What lands

  • Upstream DataFusion 54 (746d639), replacing the stale df53 base.
  • One hotdata patch: feat: table-size based cache pass-through (with_max_scan_bytes on LocalModeOptimizer + LiquidCacheLocalBuilder; parquet scans over the threshold bypass the cache), ported to df54's refactored optimizer API.

What's dropped (no longer needed)

Mechanics

This is a fast-forwardable merge commit (parents = current main + the ported df54 branch; tree = the df54+patch state), so main advances with no force-push, satisfying branch protection. The old df53 main is archived at tag pre-df54-df53-main.

Verification

  • Builds clean; cargo fmt --check + clippy clean on the touched crates.
  • Zero test regression vs. the pristine upstream base (the 19 failing tests are pre-existing Linux-only O_DIRECT tests; full functional check runs on Linux).

Part of the hotdata-wide DataFusion 53→54 upgrade (runtimedb #886).

XiangpengHao and others added 12 commits April 29, 2026 17:53
some nice refactoring to move things around
This is one of the most important yet very complicated refactor.

Many things can go wrong, especially around the datafusion integration:
concurrency, proper filter/projection/schema etc.

This is the first phase of the 2, where we stop taking new entries when
the cache is full (e.g. used up disk space).

The second phase will allow properly evicting entries from disk.
When refactoring things, a few bugs surfaced. Fixing them.
…engHao#497)

This is a major refactoring of the liquid stream, so that it does not
rely on the invariant that entires must be in the cache at streaming
time.
Instead, it will first try to read from liquid cache, and if non-exists,
it will build parquet stream and read from parquet.
When disk is full, we will run replacement to evict old items.
This pr also clean up the unnecessary policies (they don't really makes
sense)
With the latest t4, we will have real deletion and real disk replacement
## Release v0.1.13

This PR bumps all workspace crate versions to `0.1.13`.



---

**On merge**, the `publish.yml` workflow will automatically:
1. Publish all crates to crates.io
2. Create a GitHub Release with tag `v0.1.13`

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
…XiangpengHao#504)

CachedMetaReaderFactory::create_liquid_reader constructed its inner
ParquetObjectReader without the known file size, forcing parquet 58.x
onto the suffix-fetch metadata path. With a large metadata_size_hint and
a file containing page indexes, that path can slice page-index ranges
against a retained suffix using the wrong base offset, panicking with
`assertion failed: end <= remainder.len()`.

Forward the already-known object_meta.size via with_file_size() so
metadata loading uses the size-aware bounded-range path, matching
DataFusion's parquet reader factories.

Fixes XiangpengHao#503
Comment on lines +70 to +78
let mut convert = |node: &Arc<dyn ExecutionPlan>, hints: ColumnSqueezeHints| {
// Leave oversized scans as vanilla parquet reads, bypassing the cache.
if let Some(max_bytes) = max_scan_bytes
&& parquet_scan_total_bytes(node).is_some_and(|total| total > max_bytes)
{
return None;
}
convert_parquet_scan(node, &cache, hints)
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: the size-cap pass-through is the sole hotdata-specific behavior in this PR, but it has no test coverage. The existing test_plan_rewrite exercises only the default (unbounded) path, so a regression that stops honoring max_scan_bytes — or that mis-computes parquet_scan_total_bytes — would go unnoticed. Consider a test that registers a parquet table, sets with_max_scan_bytes below the file size, and asserts the scan is left as a plain ParquetSource (not wrapped in LiquidParquetSource), plus the inverse above-threshold case. (not blocking)

claude[bot]
claude Bot previously approved these changes Jul 3, 2026

@claude claude 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.

Reviewed the hotdata-specific max_scan_bytes patch on top of the DataFusion 54 upgrade. The pass-through logic is correct: returning None from the convert closure leaves oversized parquet scans as vanilla DataFusion reads. One non-blocking nit left inline about missing test coverage for the new feature.

anoop-narang and others added 2 commits July 3, 2026 15:01
Sync the fork onto upstream XiangpengHao/liquid-cache@746d639 (DataFusion
54), discarding the stale df53 fork commits. The page-index/file_size fix
is now upstream (XiangpengHao#504) and max_disk_bytes is also upstream, so the fork's
old carries are dropped. The hotdata size-cap patch is re-applied on top
in the following commit.
LocalModeOptimizer gains an optional max_scan_bytes; when set, parquet
scans whose total file size exceeds the threshold are left as vanilla
DataFusion reads instead of being wrapped by LiquidCache. Exposed via
LiquidCacheLocalBuilder::with_max_scan_bytes.

Ported onto the DataFusion 54 optimizer API (convert closure + squeeze
hints), and covered by a test asserting the above/below-threshold split.

@claude claude 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.

Reviewed the single hotdata-specific change (size-cap pass-through). The builder→optimizer wiring is correct, and the prior test-coverage gap is now closed by test_max_scan_bytes_pass_through, which asserts both the below- and above-threshold cases. Rest of the diff is the upstream DataFusion 54 adoption. LGTM.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

📊 Benchmark Comparison

Current: bd0d192a (Liquid) vs Baseline: bd0d192a (DataFusionDefault)

Query Cold Time Δ Warm Time Δ CPU Time Δ
Q1 3.0ms (3.0ms) +0.0% 0.000ms (0.000ms) +0.0% 0.000ms (0.000ms) +0.0%
Q2 10.0ms (6.0ms) +66.7% 3.8ms (5.0ms) -25.0% 6.2ms (7.0ms) -10.7%
Q3 16.0ms (11.0ms) +45.5% 5.5ms (12.0ms) -54.2% 2.5ms (22.0ms) -88.6%
Q4 17.0ms (11.0ms) +54.5% 4.0ms (12.2ms) -67.3% 1.8ms (26.5ms) -93.4%
Q5 58.0ms (54.0ms) +7.4% 43.5ms (50.8ms) -14.3% 3.0ms (25.0ms) -88.0%
Q6 150.0ms (103.0ms) +45.6% 68.8ms (104.2ms) -34.1% 18.0ms (78.8ms) -77.1%
Q7 1.0ms (1.0ms) +0.0% 0.000ms (0.000ms) +0.0% 0.000ms (0.000ms) +0.0%
Q8 8.0ms (6.0ms) +33.3% 4.8ms (6.0ms) -20.8% 7.8ms (6.2ms) +24.0%
Q9 82.0ms (83.0ms) -1.2% 82.0ms (79.5ms) +3.1% 4.2ms (42.8ms) -90.1%
Q10 118.0ms (94.0ms) +25.5% 83.0ms (89.2ms) -7.0% 8.5ms (62.2ms) -86.3%
Q11 47.0ms (24.0ms) +95.8% 21.8ms (25.0ms) -13.0% 37.8ms (35.8ms) +5.6%
Q12 50.0ms (29.0ms) +72.4% 25.8ms (29.5ms) -12.7% 42.2ms (43.0ms) -1.7%
Q13 180.0ms (102.0ms) +76.5% 83.5ms (102.2ms) -18.3% 63.5ms (80.2ms) -20.9%
Q14 369.0ms (132.0ms) +179.5% 146.0ms (134.5ms) +8.6% 108.0ms (106.5ms) +1.4%
Q15 205.0ms (90.0ms) +127.8% 90.8ms (93.5ms) -2.9% 87.0ms (97.8ms) -11.0%
Q16 81.0ms (57.0ms) +42.1% 65.2ms (60.2ms) +8.3% 3.5ms (25.5ms) -86.3%
Q17 380.0ms (152.0ms) +150.0% 200.8ms (150.2ms) +33.6% 106.8ms (106.8ms) +0.0%
Q18 382.0ms (158.0ms) +141.8% 190.8ms (151.2ms) +26.1% 98.5ms (106.2ms) -7.3%
Q19 615.0ms (281.0ms) +118.9% 300.8ms (282.8ms) +6.4% 95.0ms (148.0ms) -35.8%
Q20 13.0ms (15.0ms) -13.3% 3.0ms (12.2ms) -75.5% 6.2ms (24.8ms) -74.7%
Q21 835.0ms (180.0ms) +363.9% 263.8ms (181.5ms) +45.3% 516.5ms (282.8ms) +82.7%
Q22 1.04s (212.0ms) +389.2% 324.0ms (206.0ms) +57.3% 173.8ms (359.0ms) -51.6%
Q23 2.50s (582.0ms) +329.9% 998.5ms (590.0ms) +69.2% 547.0ms (770.2ms) -29.0%
Q24 17.61s (934.0ms) +1785.3% 784.5ms (918.0ms) -14.5% 647.2ms (2.54s) -74.5%
Q25 183.0ms (72.0ms) +154.2% 14.5ms (59.0ms) -75.4% 36.2ms (120.5ms) -69.9%
Q26 111.0ms (45.0ms) +146.7% 18.8ms (50.2ms) -62.7% 49.8ms (85.0ms) -41.5%
Q27 187.0ms (58.0ms) +222.4% 26.5ms (59.8ms) -55.6% 77.2ms (121.2ms) -36.3%
Q28 915.0ms (198.0ms) +362.1% 273.0ms (197.0ms) +38.6% 355.8ms (287.2ms) +23.8%
Q29 1.66s (1.01s) +64.8% 1.05s (1.02s) +3.3% 394.2ms (351.8ms) +12.1%
Q30 31.0ms (28.0ms) +10.7% 26.2ms (28.0ms) -6.2% 5.8ms (21.5ms) -73.3%
Q31 261.0ms (100.0ms) +161.0% 50.2ms (97.0ms) -48.2% 42.0ms (146.5ms) -71.3%
Q32 526.0ms (96.0ms) +447.9% 79.5ms (92.0ms) -13.6% 59.8ms (148.0ms) -59.6%
Q33 195.0ms (175.0ms) +11.4% 149.8ms (171.8ms) -12.8% 7.8ms (70.8ms) -89.0%
Q34 959.0ms (315.0ms) +204.4% 407.2ms (318.8ms) +27.8% 357.8ms (273.8ms) +30.7%
Q35 903.0ms (322.0ms) +180.4% 388.2ms (322.2ms) +20.5% 355.5ms (277.2ms) +28.2%
Q36 63.0ms (56.0ms) +12.5% 53.8ms (63.8ms) -15.7% 3.8ms (24.5ms) -84.7%
Q37 330.0ms (93.0ms) +254.8% 74.2ms (92.2ms) -19.5% 42.2ms (73.5ms) -42.5%
Q38 67.0ms (46.0ms) +45.7% 29.0ms (43.0ms) -32.6% 16.8ms (25.0ms) -33.0%
Q39 277.0ms (45.0ms) +515.6% 12.5ms (47.8ms) -73.8% 11.0ms (72.5ms) -84.8%
Q40 747.0ms (176.0ms) +324.4% 207.0ms (160.2ms) +29.2% 87.0ms (123.5ms) -29.6%
Q41 21.0ms (18.0ms) +16.7% 10.0ms (20.0ms) -50.0% 6.8ms (19.0ms) -64.5%
Q42 22.0ms (17.0ms) +29.4% 10.5ms (19.2ms) -45.5% 7.5ms (17.2ms) -56.5%
Q43 22.0ms (27.0ms) -18.5% 11.8ms (15.8ms) -25.4% 7.2ms (11.0ms) -34.1%

⚠️ LiquidCache is slower on 14 queries (warm)

  • Q23: warm +69.2% (998.5ms vs 590.0ms)
  • Q22: warm +57.3% (324.0ms vs 206.0ms)
  • Q21: warm +45.3% (263.8ms vs 181.5ms)
  • Q28: warm +38.6% (273.0ms vs 197.0ms)
  • Q17: warm +33.6% (200.8ms vs 150.2ms)
  • Q40: warm +29.2% (207.0ms vs 160.2ms)
  • Q34: warm +27.8% (407.2ms vs 318.8ms)
  • Q18: warm +26.1% (190.8ms vs 151.2ms)
  • Q35: warm +20.5% (388.2ms vs 322.2ms)
  • Q14: warm +8.6% (146.0ms vs 134.5ms)
  • Q16: warm +8.3% (65.2ms vs 60.2ms)
  • Q19: warm +6.4% (300.8ms vs 282.8ms)
  • Q29: warm +3.3% (1.05s vs 1.02s)
  • Q9: warm +3.1% (82.0ms vs 79.5ms)

Compared Liquid vs DataFusionDefault on the same runner
Cold Time: first iteration; Warm Time: average of remaining iterations.

@anoop-narang anoop-narang merged commit e59aa41 into main Jul 3, 2026
12 checks passed
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