Skip to content

[EPIC] Fast manifest reads for PyIceberg through pyiceberg-core #3262

Description

@mbutrovich

What's the feature are you trying to implement?

PyIceberg wants to read manifests and manifest lists through pyiceberg-core instead of its Cython Avro decoder. Today the pyiceberg-core path is 4x to 5x slower than Cython end to end. This issue tracks the iceberg-rust work needed to make it faster. The overall effort, including the PyIceberg tasks, is tracked in apache/iceberg-python#4007. This issue falls under the PyIceberg integration epic #1694 and revisits #1280.

The full benchmark writeup from @kevinjqliu, including an in-crate profile of Manifest::parse_avro and the script, is in kevinjqliu/iceberg-python#45.

Where the time goes

These numbers come from manifests written by PyIceberg (V2, deflate, 12 columns with full column stats, identity partition). pyiceberg-core is built locally from v0.10.1, once as released (opt-level = "z") and once with opt-level = 3. Each number is the best of 7 runs in ms, single threaded, on Apple Silicon. v0.10.1 predates #3028, which its PR measured as making Manifest::parse_avro about 5% faster.

entries Cython read_manifest_entries ("z") end to end ("z") read_manifest_entries (3) end to end (3)
1,000 8.7 35.3 43.9 22.2 30.8
10,000 94.1 351.0 452.3 217.4 320.4
50,000 565.9 1750.6 2308.7 1093.7 1628.0

"End to end" includes building PyIceberg ManifestEntry and DataFile objects from the binding's getters, which is what the Cython path produces. Two separate costs have to go for pyiceberg-core to beat Cython:

  • The Rust parse costs 21.7 us per entry at opt-level = 3, against 10.3 us per entry for the whole Cython path. The linked profile puts about 82% of the parse inside apache-avro, in decoding into apache_avro::Value and then resolving against the reader schema. Resolution always runs, because the reader schema iceberg-rust generates never equals a PyIceberg or Java writer schema.
  • Converting the binding's output into PyIceberg objects costs another 10.3 us per entry, as much as Cython. That cost doesn't depend on how fast the Rust parser is.

Task list

These follow-ups to Task 1 were built during that work but held back so that Task 1 changes no behavior.

Willingness to contribute

I can contribute to this feature independently

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestepicEpic issue

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions