Skip to content

Commit bdcba32

Browse files
authored
fix: zstd frame step width for alignment (#5730)
The beginning of each frame in zstd needs to align with the buffer alignment. --------- Signed-off-by: Alexander Droste <[email protected]>
1 parent 3487a1b commit bdcba32

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

encodings/zstd/src/array.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ impl ZstdArray {
330330
.get(i + 1)
331331
.copied()
332332
.unwrap_or(value_bytes.len());
333+
333334
let uncompressed = &value_bytes.slice(frame_byte_starts[i]..frame_byte_end);
334335
let compressed = compressor
335336
.compress(uncompressed)
@@ -366,8 +367,12 @@ impl ZstdArray {
366367
};
367368

368369
let value_bytes = values.byte_buffer();
370+
// Align frames to buffer alignment. This is necessary for overaligned buffers.
371+
let alignment = *value_bytes.alignment();
372+
let step_width = (values_per_frame * byte_width).div_ceil(alignment) * alignment;
373+
369374
let frame_byte_starts = (0..n_values * byte_width)
370-
.step_by(values_per_frame * byte_width)
375+
.step_by(step_width)
371376
.collect::<Vec<_>>();
372377
let Frames {
373378
dictionary,

encodings/zstd/src/test.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use vortex_array::arrays::VarBinViewArray;
99
use vortex_array::assert_arrays_eq;
1010
use vortex_array::validity::Validity;
1111
use vortex_array::vtable::ValidityHelper;
12+
use vortex_buffer::Alignment;
1213
use vortex_buffer::Buffer;
1314
use vortex_dtype::DType;
1415
use vortex_dtype::Nullability;
@@ -202,3 +203,16 @@ fn test_sliced_array_children() {
202203
let sliced = compressed.slice(0..4);
203204
sliced.children();
204205
}
206+
207+
/// Tests that each beginning of a frame in ZSTD matches
208+
/// the buffer alignment when compressing primitive arrays.
209+
#[test]
210+
fn test_zstd_frame_start_buffer_alignment() {
211+
let data = vec![0u8; 2];
212+
let aligned_buffer = Buffer::copy_from_aligned(&data, Alignment::new(8));
213+
// u8 array now has a 8-byte alignment.
214+
let array = PrimitiveArray::new(aligned_buffer, Validity::NonNullable);
215+
let compressed = ZstdArray::from_primitive(&array, 0, 1);
216+
217+
assert!(compressed.is_ok());
218+
}

0 commit comments

Comments
 (0)