Skip to content

Commit 86f2f49

Browse files
authored
Eager, parallel streaming parquet writer (#66)
1 parent 70fdd24 commit 86f2f49

12 files changed

Lines changed: 2641 additions & 11 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ parquet = { version = "^57.0.0", features = [
3636
"arrow_canonical_extension_types",
3737
] }
3838
percent-encoding = "^2.3.1"
39+
rustc-hash = "2"
3940
serde = { version = "^1.0", features = ["derive"] }
4041
serde_json = "^1.0.145"
4142
strum_macros = "^0.27.2"
@@ -79,6 +80,10 @@ harness = false
7980
name = "partitioning"
8081
harness = false
8182

83+
[[bench]]
84+
name = "transform_to_parquet"
85+
harness = false
86+
8287
[profile.release]
8388
lto = true
8489
codegen-units = 1

benches/parquet_writer.rs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,17 @@ use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_m
1111
use parquet::arrow::ArrowWriter;
1212
use parquet::file::properties::WriterProperties;
1313
use silk_chiffon::sinks::parquet::{
14-
DEFAULT_BUFFER_SIZE, StreamParquetWriter, recommended_concurrency,
14+
DEFAULT_BUFFER_SIZE, EagerParquetWriter, StreamParquetWriter, recommended_concurrency,
1515
};
16+
17+
const DEFAULT_MIN_DISPATCH_ROWS: usize = 32768;
18+
19+
fn min_dispatch_rows() -> usize {
20+
std::env::var("SILK_MIN_DISPATCH_ROWS")
21+
.ok()
22+
.and_then(|v| v.parse().ok())
23+
.unwrap_or(DEFAULT_MIN_DISPATCH_ROWS)
24+
}
1625
use tempfile::tempdir;
1726
use tokio::runtime::Runtime;
1827

@@ -215,6 +224,7 @@ impl<'a> Iterator for BatchIterator<'a> {
215224

216225
fn bench_sequential(c: &mut Criterion) {
217226
let mut group = c.benchmark_group("sequential");
227+
group.sample_size(10);
218228

219229
for config in CONFIGS {
220230
let schema = create_schema(config.cols);
@@ -298,5 +308,58 @@ fn bench_stream_parallel(c: &mut Criterion) {
298308
group.finish();
299309
}
300310

301-
criterion_group!(benches, bench_sequential, bench_stream_parallel);
311+
fn bench_eager_parallel(c: &mut Criterion) {
312+
let rt = Runtime::new().unwrap();
313+
let mut group = c.benchmark_group("eager_parallel");
314+
315+
for config in CONFIGS {
316+
let schema = create_schema(config.cols);
317+
let template = BatchTemplate::new(&schema, INPUT_BATCH_SIZE);
318+
let size = template.estimated_row_size() * config.rows as u64;
319+
320+
let concurrency = recommended_concurrency(config.cols);
321+
322+
group.throughput(Throughput::Bytes(size));
323+
group.bench_with_input(
324+
BenchmarkId::from_parameter(config),
325+
&(&schema, &template, config, concurrency),
326+
|b, (schema, template, config, concurrency)| {
327+
b.iter(|| {
328+
rt.block_on(async {
329+
let temp_dir = tempdir().unwrap();
330+
let path = temp_dir.path().join("test.parquet");
331+
let props = WriterProperties::builder().build();
332+
333+
let mut writer = EagerParquetWriter::new(
334+
&path,
335+
schema,
336+
props,
337+
config.row_group_size,
338+
DEFAULT_BUFFER_SIZE,
339+
*concurrency,
340+
min_dispatch_rows(),
341+
);
342+
343+
for batch in black_box(BatchIterator {
344+
template,
345+
remaining: config.rows,
346+
}) {
347+
writer.write(batch).await.unwrap();
348+
}
349+
writer.close().await.unwrap();
350+
});
351+
});
352+
},
353+
);
354+
}
355+
356+
group.finish();
357+
}
358+
359+
criterion_group!(
360+
benches,
361+
bench_sequential,
362+
bench_stream_parallel,
363+
bench_eager_parallel
364+
);
302365
criterion_main!(benches);

0 commit comments

Comments
 (0)