GH-50628: [C++][Parquet] Rework RecordReader to introduce flat optional optimization - #50629
GH-50628: [C++][Parquet] Rework RecordReader to introduce flat optional optimization#50629AntoinePrv wants to merge 35 commits into
Conversation
|
|
| @@ -21,29 +21,28 @@ | |||
| #include <cstdint> | |||
| #include <cstring> | |||
| #include <exception> | |||
| #include <format> | |||
There was a problem hiding this comment.
I'm afraid this won't be available on some of our CI platforms.
| using V = smallest_int_t<T, U>; | ||
| return std::min<V>(clamp_to<V>(x), clamp_to<V>(y)); |
There was a problem hiding this comment.
If both values are always positive, you can just static_cast<smallest_int>(std::min<largest_int>(x, y)), no?
| /// re-encoding into an Arrow validity bitmap, it decodes straight into the bitmap. | ||
| /// | ||
| /// @see LevelDecoder | ||
| class LevelToBitmapDecoder { |
There was a problem hiding this comment.
I think we want to use polymorphism (i.e. virtual methods on a base interface) rather than independent classes.
There was a problem hiding this comment.
The issue is that Decode takes fundamentally different arguments:
- In the general case, an
int16_t*array where the data type correspond to one value - In the bitmap case, a
uint8_t*array + bit offset to find the exact pointed bit.
So we'd need to also dynamically dispatch the output type here, which IMHO brings extra complexity and performance hit (virtual polymorphism brings little since this is fully private and used in separate classes).
If this is about code reuse, I would suggest:
- Make a de-pimpled templated
LevelDecoder - Either:
- Wrap it in a pimpl to make the existing
LevelDecoder - OR split
rle_encoding_internal.hppinto arle_decoding_fwd_internal.hpp+rle_decoding_internal.hppto have a light class definition (without function definitions and other headers) to include incolumn_reader.h.
- Wrap it in a pimpl to make the existing
There was a problem hiding this comment.
The issue is that
Decodetakes fundamentally different arguments:
* In the general case, anint16_t*array where the data type correspond to one value
* In the bitmap case, auint8_t*array + bit offset to find the exact pointed bit.
Ideally the RecordReader would not see levels values anymore, so this discrepancy would disappear.
| using DefLevelDecoder = typename Traits::DefLevelDecoder; | ||
| using RepLevelDecoder = typename Traits::RepLevelDecoder; |
There was a problem hiding this comment.
I don't think it's a good idea to introduce more templating in these classes. As I said above, hopefully we should be able to decouple more by using an abstract interface for the level decoders.
There was a problem hiding this comment.
This is mostly tied to what we can achieve with the LevelDecoder, but I think the templating can help the performance here (and this is private so it is not an extra burden on the user).
There was a problem hiding this comment.
Looking at column_reader.cc.o in release mode it goes from 720K in main to 2.1M in this PR (but it's not the worst offender).
We could first remove the template inheritance in the array and binary and readers that is not as critical if we want to save some space.
There was a problem hiding this comment.
The concern is more to be able to have several LevelDecoder implementations without defining corresponding RecordReader specializations.
|
Initial benchmarks at this point on Linux x86-64 Parquet decoder and reader benchmarks on Linux x86-64 |
Rationale for this change
WIP
What changes are included in this PR?
Are these changes tested?
Tests are expected to fail until we figure out what
int16_t* RecordReader::def_levels()should do.Are there any user-facing changes?
RecordReaderfor flat optional #50628