Skip to content

Commit eff28d9

Browse files
author
B Vadlamani
committed
address_review_comments
1 parent 436cce4 commit eff28d9

2 files changed

Lines changed: 30 additions & 2 deletions

File tree

benchmarks/src/hj.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,8 @@ const HASH_QUERIES: &[HashJoinQuery] = &[
302302
probe_size: "60M",
303303
},
304304
// RightSemi Join benchmarks with Int32 keys
305-
// Fanout: N/A for semi joins (returns at most one row per probe key)
305+
// Matching ratio: 1:1 (build keys are unique, each probe matches at most 1 build row)
306+
// Semi joins can short-circuit after first match, so hit rate affects performance.
306307
//
307308
// Q16: RightSemi, Small build (25 rows), 100% Hit rate
308309
// Build Side: nation (25 rows) | Probe Side: customer (1.5M rows)
@@ -344,7 +345,8 @@ const HASH_QUERIES: &[HashJoinQuery] = &[
344345
probe_size: "60M_RightSemi",
345346
},
346347
// RightAnti Join benchmarks with Int32 keys
347-
// Fanout: N/A for anti joins (returns at most one row per probe key)
348+
// Matching ratio: 1:1 (build keys are unique, each probe matches at most 1 build row)
349+
// Anti joins can short-circuit after first match, so hit rate affects performance.
348350
//
349351
// Q19: RightAnti, Small build (25 rows), 100% Hit rate (no output)
350352
// Build Side: nation (25 rows) | Probe Side: customer (1.5M rows)

datafusion/physical-plan/benches/hash_join_semi_anti.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@
1616
// under the License.
1717

1818
//! Criterion benchmarks for Hash Join with RightSemi/RightAnti joins with Int32 keys.
19+
//!
20+
//! ## Key Benchmark Axes
21+
//!
22+
//! - **Density**: The ratio of distinct key values to the key range span.
23+
//! For example, keys [0, 2, 4, 6, 8] have density = 5/9 ≈ 55% (5 distinct values
24+
//! in a range of 9). Density affects hash table memory layout and cache behavior.
25+
//! Lower density means keys are more spread out, leading to more cache misses.
26+
//!
27+
//! - **Hit Rate**: The percentage of probe rows that find a match in the build side.
28+
//! This controls how often the join produces output rows.
29+
//!
30+
//! Semi/anti joins can short-circuit after finding the first match, so these
31+
//! benchmarks help evaluate optimization strategies for existence checks.
1932
2033
use std::sync::Arc;
2134

@@ -157,6 +170,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
157170
let mut group = c.benchmark_group("hash_join_semi_anti");
158171

159172
// Build side: 100K rows, Probe side: 1M rows
173+
// Matching ratio: 1:1 (build keys are unique, each probe matches at most 1 build row)
160174
let build_rows = 100_000;
161175
let probe_rows = 1_000_000;
162176

@@ -165,6 +179,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
165179
// =========================================================================
166180

167181
// RightSemi - 100% Density, 100% hit rate
182+
// Keys: 0..100K contiguous, all probe rows find a match
168183
{
169184
let left_batches = build_batches(build_rows, build_rows, 0, &s);
170185
let right_batches = build_batches(probe_rows, build_rows, 0, &s);
@@ -178,6 +193,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
178193
}
179194

180195
// RightSemi - 100% Density, 10% hit rate
196+
// Keys: 0..100K contiguous, only 10% of probe rows find a match
181197
{
182198
let left_batches = build_batches(build_rows, build_rows, 0, &s);
183199
let right_batches = build_batches(probe_rows, build_rows * 10, 0, &s);
@@ -191,6 +207,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
191207
}
192208

193209
// RightSemi - 50% Density, 100% hit rate
210+
// Keys: 0, 2, 4, ... (sparse, multiplier=2), all probe rows find a match
194211
{
195212
let left_batches = build_batches_sparse(build_rows, build_rows, 0, 2, &s);
196213
let right_batches = build_batches_sparse(probe_rows, build_rows, 0, 2, &s);
@@ -204,6 +221,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
204221
}
205222

206223
// RightSemi - 50% Density, 10% hit rate
224+
// Keys: 0, 2, 4, ... (sparse), only 10% of probe rows find a match
207225
{
208226
let left_batches = build_batches_sparse(build_rows, build_rows, 0, 2, &s);
209227
let right_batches = build_batches_sparse(probe_rows, build_rows * 10, 0, 2, &s);
@@ -217,6 +235,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
217235
}
218236

219237
// RightSemi - 10% Density, 100% hit rate
238+
// Keys: 0, 10, 20, ... (very sparse, multiplier=10), all probe rows find a match
220239
{
221240
let left_batches = build_batches_sparse(build_rows, build_rows, 0, 10, &s);
222241
let right_batches = build_batches_sparse(probe_rows, build_rows, 0, 10, &s);
@@ -230,6 +249,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
230249
}
231250

232251
// RightSemi - 10% Density, 10% hit rate
252+
// Keys: 0, 10, 20, ... (very sparse), only 10% of probe rows find a match
233253
{
234254
let left_batches = build_batches_sparse(build_rows, build_rows, 0, 10, &s);
235255
let right_batches = build_batches_sparse(probe_rows, build_rows * 10, 0, 10, &s);
@@ -247,6 +267,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
247267
// =========================================================================
248268

249269
// RightAnti - 100% Density, 100% hit rate (no output)
270+
// Keys: 0..100K contiguous, all probe rows find a match -> no output
250271
{
251272
let left_batches = build_batches(build_rows, build_rows, 0, &s);
252273
let right_batches = build_batches(probe_rows, build_rows, 0, &s);
@@ -260,6 +281,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
260281
}
261282

262283
// RightAnti - 100% Density, 10% hit rate (90% output)
284+
// Keys: 0..100K contiguous, only 10% of probe rows find a match -> 90% output
263285
{
264286
let left_batches = build_batches(build_rows, build_rows, 0, &s);
265287
let right_batches = build_batches(probe_rows, build_rows * 10, 0, &s);
@@ -273,6 +295,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
273295
}
274296

275297
// RightAnti - 50% Density, 100% hit rate (no output)
298+
// Keys: 0, 2, 4, ... (sparse), all probe rows find a match -> no output
276299
{
277300
let left_batches = build_batches_sparse(build_rows, build_rows, 0, 2, &s);
278301
let right_batches = build_batches_sparse(probe_rows, build_rows, 0, 2, &s);
@@ -286,6 +309,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
286309
}
287310

288311
// RightAnti - 50% Density, 10% hit rate (90% output)
312+
// Keys: 0, 2, 4, ... (sparse), only 10% of probe rows find a match -> 90% output
289313
{
290314
let left_batches = build_batches_sparse(build_rows, build_rows, 0, 2, &s);
291315
let right_batches = build_batches_sparse(probe_rows, build_rows * 10, 0, 2, &s);
@@ -299,6 +323,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
299323
}
300324

301325
// RightAnti - 10% Density, 100% hit rate (no output)
326+
// Keys: 0, 10, 20, ... (very sparse), all probe rows find a match -> no output
302327
{
303328
let left_batches = build_batches_sparse(build_rows, build_rows, 0, 10, &s);
304329
let right_batches = build_batches_sparse(probe_rows, build_rows, 0, 10, &s);
@@ -312,6 +337,7 @@ fn bench_hash_join_semi_anti(c: &mut Criterion) {
312337
}
313338

314339
// RightAnti - 10% Density, 10% hit rate (90% output)
340+
// Keys: 0, 10, 20, ... (very sparse), only 10% of probe rows find a match -> 90% output
315341
{
316342
let left_batches = build_batches_sparse(build_rows, build_rows, 0, 10, &s);
317343
let right_batches = build_batches_sparse(probe_rows, build_rows * 10, 0, 10, &s);

0 commit comments

Comments
 (0)