-
Notifications
You must be signed in to change notification settings - Fork 810
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
Truncate IPC record batch #2040
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2040 +/- ##
==========================================
+ Coverage 83.55% 83.60% +0.05%
==========================================
Files 222 223 +1
Lines 58230 58539 +309
==========================================
+ Hits 48656 48944 +288
- Misses 9574 9595 +21
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not very familiar with IPC, so just give some small nits I find.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good, I think there is an issue with the way bitmaps are currently handled but I think this should just be a case of using Buffer::bit_slice
or similar
) { | ||
// Rebase offsets and truncate values | ||
let new_offsets = get_zero_based_value_offsets(array_data); | ||
offset = write_buffer(new_offsets.as_slice(), buffers, arrow_data, offset); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely something that could be left to another PR, but I do wonder if there might be some way to write the new offsets directly without buffering them first. I'm not very familiar with the IPC code so not sure how feasible this may be
❤️ -- thank you @viirya Note we have some code in IOx to workaround the lack of this feature (described in https://github.com/influxdata/influxdb_iox/issues/1133): I wonder if this PR also closes #208? |
Yes, flight data also uses IPC to encode record batch. This also closes #208 too. |
Updated the PR description to match |
Apologies I'm trying to review this, but I'm extremely confused as to how this has been and is working, I can't find where the IPC writer makes use of the ArrayData offset, and am therefore at a loss as to how slicing has historically been being preserved. Could you possibly point me at the relevant code, as far as I can tell it previously wrote the entirety of the buffers, but I can't work out how the reader then knows to ignore most of this? Edit: It would appear that the previous logic was and still is simply broken... |
arrow/src/ipc/writer.rs
Outdated
); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert_eq!( | |
deserialize(serialize_without_truncate(&record_batch_slice)), | |
record_batch_slice | |
); |
Or something, basically I think the non-sliced logic was and still is wrong.
I was looking for how the reader knows how to ignore it. But I didn't find it. Then I realized that previously the writer wrote the entire buffers. For the reader, it sets offsets from zero and reads the buffers from incorrect positions. So I think it is a bug that sliced record batch cannot be read correctly after IPC. We can reproduce it: fn create_batch() -> RecordBatch {
let schema = Schema::new(vec![
Field::new("a", DataType::Int32, true),
Field::new("b", DataType::Utf8, true),
]);
let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
let b = StringArray::from(vec!["a", "b", "c", "d", "e"]);
RecordBatch::try_new(Arc::new(schema), vec![Arc::new(a), Arc::new(b)])
.unwrap()
}
let big_record_batch = create_batch();
let offset = 2;
let record_batch_slice = big_record_batch.slice(offset, 3); Original record batches:
Record batches after IPC serialization/deserialzation:
|
That's said that we need to truncate it without the option. I don't find C++ implementation has an option for that actually. |
Perhaps we should make it non-optional then, I had thought the offset was separately preserved, given it isn't, there doesn't seem to be a reason to have the option |
Unrelated error on Windows CI:
|
I think there is more to be done in this vein, e.g. ListArray, StructArray, etc... but this is a good step forward. Thank you 🙂 |
Thanks @alamb @tustvold @JasonLi-cn @HaoYang670 |
I don't find C++ implementation does truncation for ListArray, StructArray, but maybe I miss it when reading the code. I will re-check this. |
Benchmark runs are scheduled for baseline = 5e520bb and contender = 86543a4. 86543a4 is a master commit associated with this PR. Results will be available as each benchmark for each run completes. |
@tustvold is the remaining work recorded anywhere? I am happy to write up a ticket but I don't understand the issue well enough to do so at this moment |
Filed #2080 to track follow up work, I personally think we should accelerate efforts to remove offset from ArrayData, as opposed to continuing to work around it in various places |
Which issue does this PR close?
Closes #1528.
Closes #208
Rationale for this change
When serialize RecordBatch through IPC, we should truncate it to only serialize the necessary part if the batch is sliced.
C++ implementation also truncates it:
https://github.com/apache/arrow/blob/master/cpp/src/arrow/ipc/writer.cc#L351
https://github.com/apache/arrow/blob/master/cpp/src/arrow/ipc/writer.cc#L327
What changes are included in this PR?
Truncate arrays of record batch when serializing it through IPC. Following C++, we truncate arrays of numeric type, temporal types, fixed size binary type and base binary types (binary, string).
Are there any user-facing changes?