Skip to content

feat: replace apache-avro with serde_avro_fast and parallelize manifest reads#203

Merged
JingsongLi merged 1 commit intoapache:mainfrom
JingsongLi:manifest_read
Apr 4, 2026
Merged

feat: replace apache-avro with serde_avro_fast and parallelize manifest reads#203
JingsongLi merged 1 commit intoapache:mainfrom
JingsongLi:manifest_read

Conversation

@JingsongLi
Copy link
Copy Markdown
Contributor

Purpose

Switch Avro deserialization from apache-avro (Value intermediate repr) to serde_avro_fast (direct bytes→struct), eliminating redundant allocations for ~10-20x deserialization speedup. Read manifest files concurrently with buffer_unordered(64) instead of sequentially.

Sub task of #173

Brief change log

Tests

API and Format

Documentation

pub bucket: i32,
pub level: i32,
pub file_name: String,
pub extra_files: Vec<String>,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Identifier must be aligned with Java, otherwise there will be exceptions.

@JingsongLi JingsongLi force-pushed the manifest_read branch 3 times, most recently from e557c26 to a194898 Compare April 4, 2026 01:05
Copy link
Copy Markdown
Contributor

@luoyuxia luoyuxia left a comment

Choose a reason for hiding this comment

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

@JingsongLi Thanks for the pr. Left minor comment. PTAL

Comment thread crates/paimon/src/table/table_scan.rs Outdated
let mut deleted_entry_keys = HashSet::new();
let mut added_entries = Vec::new();

let mut map: IndexMap<Identifier, ManifestEntry> = IndexMap::with_capacity(entries.len());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm curious why this change is needed.

The previous implementation mostly follows py-paimon. With the current code, we may read two manifest entries like [Delete(id), Add(id)].
Because manifests are read concurrently, Delete(id) may be observed first. In that case, the later Add(id) would be kept by the current IndexMap + shift_remove logic.

However, IIUC, that is incorrect: once Delete(id) exists, the corresponding Add(id) should be filtered out rather than kept.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There aren't many deleted entries, it doesn't seem very meaningful to modify it to read twice, as it will repeatedly read the manifest containing the deleted entry.

If we don't read it twice, the current implementation is quite reasonable, we only need to traverse it once.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

But I think the previous implementation is indeed safer. I will revert here.

Copy link
Copy Markdown
Contributor

@luoyuxia luoyuxia left a comment

Choose a reason for hiding this comment

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

Thanks. +1

Copy link
Copy Markdown

@yuzelin yuzelin left a comment

Choose a reason for hiding this comment

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

+1

…st reads

Switch Avro deserialization from apache-avro (Value intermediate repr) to
serde_avro_fast (direct bytes→struct), eliminating redundant allocations
for ~10-20x deserialization speedup. Read manifest files concurrently
with buffer_unordered(64) instead of sequentially.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@JingsongLi JingsongLi merged commit 587389b into apache:main Apr 4, 2026
8 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