Skip to content

Use IPC instead of Elixir rows for table replication (15.9x faster) - #35

Merged
cigrainger merged 1 commit into
mainfrom
perf/ipc-table-replication
Mar 25, 2026
Merged

cigrainger merged 1 commit into
mainfrom
perf/ipc-table-replication

Conversation

@cigrainger

Copy link
Copy Markdown
Contributor

Summary

When a computed %Dux{} (table ref) is distributed to workers, it was going through Elixir rows:

  1. table_to_rows → list of maps (expensive materialization)
  2. Sent as {:list, rows} in pipeline struct (large Erlang term)
  3. Workers re-ingest via rows_to_columns → ADBC (rebuild Arrow from scratch)

Now uses Arrow IPC — the same binary format workers already use for results:

  1. table_to_ipc → compact Arrow binary
  2. Sent as {:ipc, binary} (binary copy, no term encoding)
  3. Workers table_from_ipc → zero-copy ADBC ingest

Changes:

  • Add {:ipc, binary} source type in QueryBuilder
  • Partitioner.replicate/2 uses IPC instead of rows
  • Shuffle.ensure_worker_safe/1 uses IPC instead of rows
  • Inspect handles {:ipc, _} source display

Benchmark (2 local workers)

Benchmark Before (median) After (median) Speedup
Replicate 1K rows 16ms 27ms ~same (IPC overhead on small data)
Replicate 10K rows 381ms 24ms 15.9x
Broadcast join (computed right) 260ms 72ms 3.6x

Test plan

  • 29 distributed tests pass (0 failures)
  • Credo strict clean
  • Benchmarks before and after

🤖 Generated with Claude Code

When a computed %Dux{} (table ref) is distributed to workers, it was:
1. table_to_rows → Elixir list of maps
2. Sent as {:list, rows} in the pipeline struct
3. Workers re-ingested via rows_to_columns → ADBC ingest

Now uses the IPC path:
1. table_to_ipc → compact Arrow binary
2. Sent as {:ipc, binary} in the pipeline struct
3. Workers deserialize via zero-copy ADBC ingest

Added {:ipc, binary} as a source type in QueryBuilder. IPC table refs
are kept alive in the process dictionary during query execution and
cleaned up via clear_ipc_refs/0 in all worker query paths.

Benchmark (2 workers):
  Replicate 1K rows:    16ms → 27ms (IPC overhead on small data, negligible)
  Replicate 10K rows:  381ms → 24ms (15.9x faster)
  Broadcast join:      260ms → 72ms (3.6x faster)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cigrainger
cigrainger force-pushed the perf/ipc-table-replication branch from c1dcdce to 829092b Compare March 25, 2026 01:45
@cigrainger
cigrainger merged commit 95d6b60 into main Mar 25, 2026
5 checks passed
@cigrainger
cigrainger deleted the perf/ipc-table-replication branch March 25, 2026 01:53
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