Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: Fast decision for Parquet dictionary encoding #19256

Merged
merged 4 commits into from
Oct 16, 2024

Conversation

coastalwhite
Copy link
Collaborator

This PR adds two things:

  1. HyperLogLog to determine estimate the cardinality of an array. If the estimated cardinality is too high, no group-by has to be done. This speeds up Parquet writing by ~2x for high cardinality data.
  2. An extension of the fast path for integers. Where if the min and the max are close enough, a bitmask is created to determine the cardinality. If cardinality is low enough or the cardinality is too high, the HyperLogLog path can be skipped. This can also lead to more than 2x improvements while writing.

This PR adds two things:
1. HyperLogLog to determine estimate the cardinality of an array. If the
   estimated cardinality is too high, no group-by has to be done. This speeds
   up Parquet writing by ~2x for high cardinality data.
2. An extension of the fast path for integers where if the min and the max are
   close enough, a bitmask is created to determine the cardinality. If
   cardinality is low enough or the cardinality is too high, the HyperLogLog
   path can be skipped. This can also lead to more than 2x improvements while
   writing.
@github-actions github-actions bot added performance Performance issues or improvements python Related to Python Polars rust Related to Rust Polars labels Oct 16, 2024
Copy link

codecov bot commented Oct 16, 2024

Codecov Report

Attention: Patch coverage is 55.98291% with 103 lines in your changes missing coverage. Please review.

Project coverage is 79.97%. Comparing base (e29e9df) to head (6fc39e9).
Report is 16 commits behind head on main.

Files with missing lines Patch % Lines
crates/polars-compute/src/cardinality.rs 32.29% 65 Missing ⚠️
crates/polars-arrow/src/types/native.rs 0.00% 19 Missing ⚠️
...tes/polars-parquet/src/parquet/read/page/reader.rs 0.00% 13 Missing ⚠️
...rates/polars-parquet/src/arrow/write/dictionary.rs 94.33% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #19256      +/-   ##
==========================================
+ Coverage   79.68%   79.97%   +0.29%     
==========================================
  Files        1532     1529       -3     
  Lines      209211   209848     +637     
  Branches     2416     2416              
==========================================
+ Hits       166710   167828    +1118     
+ Misses      41953    41471     -482     
- Partials      548      549       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment on lines +54 to +57
for v in array.iter() {
let v = v.copied().unwrap_or_default();
hll.add(&v.to_total_ord());
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

question: Not sure how big these arrays are, but if they are full column length, does it make sense to partition the work of computing the cardinality across rows, producing a partial estimate in each thread and then using HyperLogLog::merge to reduce across threads?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

These arrays are equally large as a row group in parquet.

I don't really see much benefit in parallelizing here, because we already parallelize over columns and row groups. So unless you have a short dataframe with few columns, you probably won't see any sleeping threads.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah, sure.

@ritchie46 ritchie46 merged commit 780430f into pola-rs:main Oct 16, 2024
18 of 20 checks passed
@coastalwhite coastalwhite deleted the perf/pq-write-dict-decide branch October 16, 2024 14:47
@c-peters c-peters added the accepted Ready for implementation label Oct 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted Ready for implementation performance Performance issues or improvements python Related to Python Polars rust Related to Rust Polars
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants