Skip to content

[PERF] Simplify the conditional_join Python/Rust boundary - #1672

Open
samukweku wants to merge 2 commits into
devfrom
1649-simplify-conditional-join-rust-boundary
Open

[PERF] Simplify the conditional_join Python/Rust boundary#1672
samukweku wants to merge 2 commits into
devfrom
1649-simplify-conditional-join-rust-boundary

Conversation

@samukweku

Copy link
Copy Markdown
Collaborator

Summary

  • Remove the duplicate _sum_starts_ends definition in _agg_functions.py (the later copy was silently shadowing the first).
  • Replace ~87 repeated per-call dtype-dispatch dicts across _agg_functions.py, _compare.py, and _binary_search.py with one cached dispatcher, _rs_func (new janitor/functions/_conditional_join/_dtype_dispatch.py). Unsupported-dtype errors keep the exact same KeyError message as before.
  • Swap janitor_rs.repeat_index for np.repeat at all 6 maintained-path call sites (_helpers.py ×4, _range_indices.py, _greater_than_indices.py, _less_than_indices.py). repeat_index is a literal np.repeat equivalent (verified in janitor-rs/src/index_builder.rs) and benchmarks faster.
  • Other Rust kernels shown to be beneficial (binary searches, ragged comparisons, reorder_index, positional-index construction) are untouched and stay in Rust.
  • janitor_rs.repeat_index itself is now unused on the maintained path but is left in place in janitor-rs for now — flagging here for coordinated removal in a separate pyjanitor-devs/janitor-rs PR, per this issue's proposed scope.

Benchmarks

repeat_index (Rust) vs np.repeat, timeit-measured, mean of several reps:

rows output rows repeat_index np.repeat np.repeat faster by
50 ~110 0.74µs 0.40µs 46%
1,000,000 ~2,000,000 5.41ms 4.75ms 12%
10,000,000 20,001,550 61.88ms 57.58ms 7.0%
50,000,000 99,993,543 302.85ms 281.28ms 7.1%

No regression at any scale tested; consistent with the ~8-12% improvement cited in the issue.

Test plan

  • pytest tests/functions/test_conditional_join.py — 247 passed, 1 skipped (pre-existing, unrelated)
  • New tests: _rs_func dispatch correctness, unsupported-dtype KeyError parity, np.repeat/repeat_index output parity (empty, zero-counts, mixed-counts, 1000-row)
  • pre-commit run --all-files on changed files (ruff check, ruff format, pydoclint, interrogate) — all pass

Issue #1649

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01V3KAbkp6JV96KYXNc6EJmN

Remove a duplicate _sum_starts_ends definition, replace ~87 repeated
per-call dtype-dispatch dicts in _agg_functions.py/_compare.py/
_binary_search.py with one cached dispatcher (_rs_func), and swap
repeat_index calls for np.repeat, which benchmarks faster at every
scale tested and is more immediately readable.

Issue #1649 @samukweku

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3KAbkp6JV96KYXNc6EJmN
@github-actions

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://pyjanitor-devs.github.io/pyjanitor/pr-preview/pr-1672/

Built to branch gh-pages at 2026-08-21 22:24 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@samukweku
samukweku marked this pull request as draft August 21, 2026 22:27
@samukweku samukweku self-assigned this Aug 21, 2026
@samukweku
samukweku requested a review from ericmjl August 21, 2026 22:27
@samukweku
samukweku marked this pull request as ready for review August 21, 2026 22:32
@samukweku
samukweku force-pushed the 1649-simplify-conditional-join-rust-boundary branch from 35b31ef to db93539 Compare August 26, 2026 04:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant