Add Dask - #1053
Merged
Merged
Conversation
Implements #892. Dask is "pandas in parallel", so this mirrors the pandas port: a FastAPI server wraps a Dask DataFrame behind the install/start/check/stop/load/ query/data-size interface, and queries.sql holds one Python expression per line (eval()'d by the server), just like pandas/polars. Dask-specific choices: - Uses a local cluster of worker processes (dask.distributed.LocalCluster) for real multi-core parallelism; the frame is persisted in cluster memory so load time is comparable to the pandas/polars in-memory model. - Reads the partitioned dataset (hits_0..99.parquet) — one partition per file is Dask's natural layout. - Operations are lazy, so the server materialises each result with dask.compute() and rolls that into the query timing. - Queries are close to the pandas port, diverging only where Dask's API does: COUNT(DISTINCT) combined with other aggregates (Q10, Q23) uses Dask's documented custom nunique aggregation, LIMIT/OFFSET tails (Q39-43) compute the small top-N to pandas then slice (Dask has no positional iloc), and Q8/Q26/Q27 use nlargest/sort_values since Dask Series lacks sort_values. All 43 queries validated against a synthetic dataset both with the threaded scheduler and a real distributed LocalCluster, and end-to-end through the HTTP server; cluster teardown on shutdown leaves no orphaned workers across the harness's stop/start/reload cycles. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
alexey-milovidov
had a problem deploying
to
benchmark-approval
July 23, 2026 17:09 — with
GitHub Actions
Error
alexey-milovidov
temporarily deployed
to
benchmark-approval
July 23, 2026 19:22 — with
GitHub Actions
Inactive
Contributor
|
Results for Logs:
|
alexey-milovidov
temporarily deployed
to
benchmark-approval
July 23, 2026 22:40 — with
GitHub Actions
Inactive
Contributor
|
The run of Logs:
|
Contributor
|
Results for Logs:
|
Contributor
|
The run of Logs:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #892.
Adds a Dask entry. Dask is "pandas in parallel", so this mirrors the existing pandas port: a small FastAPI server wraps a Dask DataFrame behind the standard
install/start/check/stop/load/query/data-sizeinterface, andqueries.sqlholds one Python expression per line that the servereval()s — exactly the pattern used bypandasandpolars-dataframe.Design
dask.distributed.LocalClusterof worker processes gives real multi-core execution. The frame ispersist()ed into cluster memory (andwait()ed on) so load time is comparable to the pandas/polars in-memory model.BENCH_DURABLE=no, so the harness reloads before each cold query and rolls that into the cold try, as with the other in-memory dataframe systems.hits_0..99.parquet) — one partition per file is Dask's natural layout (BENCH_DOWNLOAD_SCRIPT=download-hits-parquet-partitioned).dask.compute()and timeseval()+compute()together (mirroring pandas, whereeval()does all the work).dask.compute()recurses into tuples/lists, so the tuple queries (3, 7) and the 90-sum query (30) compute in one pass.Query translation
Queries stay close to the pandas port, diverging only where Dask's API does:
COUNT(DISTINCT)alongside other aggregates): Dask's built-ingroupby.agghas nonunique, so these use Dask's documented customnuniqueaggregation.LIMIT … OFFSET): Dask has no positionaliloc, so these take the small top-N withnlargestand slice in pandas aftercompute()(SQL-faithful, matching howpolars-dataframedoes it — not the pandas port'snlargest(10).iloc[1000:]quirk that returns empty).Serieshas nosort_values, so these usenlargest/ framesort_values.Validation
All 43 queries were validated against a synthetic dataset under both the threaded scheduler and a real distributed
LocalCluster, and end-to-end through the HTTP server. Verified that cluster teardown on shutdown leaves no orphaned worker processes across the harness's repeated stop/start/reload cycles. Real timings still need a run on a benchmark machine (aarch64 dev box can't produce the x86 result set).🤖 Generated with Claude Code