Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions dask/benchmark.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash
export BENCH_DOWNLOAD_SCRIPT="download-hits-parquet-partitioned"
export BENCH_DURABLE=no
# Dask runs Python expressions directly (server eval()s them).
# queries.sql holds those Python expressions, one per line, so the
# default BENCH_QUERIES_FILE=queries.sql in lib/benchmark-common.sh
# picks them up unchanged.
# Skip the pre-snapshot ./stop+./start cycle: the loaded
# state lives only in the daemon's process memory (in-process
# DataFrame, cluster worker heaps) and stopping wipes it. The
# playground agent reads this and snapshots the running daemon.
export PLAYGROUND_SKIP_RESTART_BEFORE_SNAPSHOT=yes
exec ../lib/benchmark-common.sh
4 changes: 4 additions & 0 deletions dask/check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
set -e

curl -sf http://127.0.0.1:8000/health | grep -q '"ok":true'
4 changes: 4 additions & 0 deletions dask/data-size
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
set -e

curl -sS http://127.0.0.1:8000/data-size | python3 -c 'import json,sys; print(json.load(sys.stdin)["bytes"])'
12 changes: 12 additions & 0 deletions dask/install
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash
set -e

sudo apt-get update -y
sudo apt-get install -y python3-pip python3-venv

if [ ! -d myenv ]; then
python3 -m venv myenv
fi
# shellcheck disable=SC1091
source myenv/bin/activate
pip install --quiet "dask[dataframe,distributed]" pyarrow fastapi uvicorn
25 changes: 25 additions & 0 deletions dask/load
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash
set -e

# See duckdb-memory/load for the rationale — the old one-liner
# elapsed=$(curl -sS ... | python3 -c '...elapsed...')
# masked curl/JSON failures with `set -e` and produced a successful-looking
# zero-timing run when the server died mid-ingest. Capture body and
# diagnose explicitly.
body=$(curl -sS -X POST http://127.0.0.1:8000/load 2>&1) || {
echo "load: curl to /load failed:" >&2
printf '%s\n' "$body" >&2
echo "load: server may have been OOM-killed during ingest" >&2
exit 1
}

elapsed=$(printf '%s' "$body" | python3 -c \
'import json,sys;print(json.load(sys.stdin)["elapsed"])' 2>&1) || {
echo "load: /load did not return valid {\"elapsed\": ...} JSON:" >&2
printf '%s\n' "$body" >&2
exit 1
}

echo "Load (server-reported): ${elapsed}s"

sync
43 changes: 43 additions & 0 deletions dask/queries.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
hits.count()
hits[hits['AdvEngineID'] != 0].count()
(hits['AdvEngineID'].sum(), hits.shape[0], hits['ResolutionWidth'].mean())
hits['UserID'].mean()
hits['UserID'].nunique()
hits['SearchPhrase'].nunique()
(hits['EventDate'].min(), hits['EventDate'].max())
hits[hits['AdvEngineID'] != 0].groupby('AdvEngineID').size().rename('c').reset_index().sort_values('c', ascending=False)
hits.groupby('RegionID')['UserID'].nunique().nlargest(10)
hits.groupby('RegionID').agg(AdvEngineID=('AdvEngineID', 'sum'), c=('WatchID', 'size'), ResolutionWidth=('ResolutionWidth', 'mean'), UserID=('UserID', nunique)).nlargest(10, 'c')
hits[hits['MobilePhoneModel'] != ''].groupby('MobilePhoneModel')['UserID'].nunique().nlargest(10)
hits[hits['MobilePhoneModel'] != ''].groupby(['MobilePhone', 'MobilePhoneModel'])['UserID'].nunique().nlargest(10)
hits[hits['SearchPhrase'] != ''].groupby('SearchPhrase').size().nlargest(10)
hits[hits['SearchPhrase'] != ''].groupby('SearchPhrase')['UserID'].nunique().nlargest(10)
hits[hits['SearchPhrase'] != ''].groupby(['SearchEngineID', 'SearchPhrase']).size().nlargest(10)
hits.groupby('UserID').size().nlargest(10)
hits.groupby(['UserID', 'SearchPhrase']).size().nlargest(10)
hits.groupby(['UserID', 'SearchPhrase']).size().head(10)
hits.groupby([hits['UserID'], hits['EventTime'].dt.minute, 'SearchPhrase']).size().nlargest(10)
hits[hits['UserID'] == 435090932899640449]
hits[hits['URL'].str.contains('google')].shape[0]
hits[hits['URL'].str.contains('google') & (hits['SearchPhrase'] != '')].groupby('SearchPhrase').agg(URL=('URL', 'min'), c=('SearchPhrase', 'size')).nlargest(10, 'c')
hits[hits['Title'].str.contains('Google') & ~hits['URL'].str.contains('.google.') & (hits['SearchPhrase'] != '')].groupby('SearchPhrase').agg(URL=('URL', 'min'), Title=('Title', 'min'), c=('SearchPhrase', 'size'), UserID=('UserID', nunique)).nlargest(10, 'c')
hits[hits['URL'].str.contains('google')].nsmallest(10, 'EventTime')
hits[hits['SearchPhrase'] != ''].nsmallest(10, 'EventTime').compute()[['SearchPhrase']]
hits[hits['SearchPhrase'] != ''][['SearchPhrase']].sort_values('SearchPhrase').head(10, npartitions=-1)
hits[hits['SearchPhrase'] != ''].sort_values(['EventTime', 'SearchPhrase']).head(10, npartitions=-1)[['SearchPhrase']]
hits[hits['URL'] != ''].assign(l=hits['URL'].str.len()).groupby('CounterID').agg(l=('l', 'mean'), c=('URL', 'size')).query('c > 100000').nlargest(25, 'l')
hits[hits['Referer'] != ''].assign(k=lambda d: d['Referer'].str.extract('^https?://(?:www\\.)?([^/]+)/.*$')[0], l=lambda d: d['Referer'].str.len()).groupby('k').agg(l=('l', 'mean'), c=('Referer', 'size'), min_referer=('Referer', 'min')).query('c > 100000').nlargest(25, 'l')
[(hits['ResolutionWidth'] + i).sum() for i in range(90)]
hits[hits['SearchPhrase'] != ''].groupby(['SearchEngineID', 'ClientIP']).agg(c=('SearchEngineID', 'size'), IsRefreshSum=('IsRefresh', 'sum'), AvgResolutionWidth=('ResolutionWidth', 'mean')).nlargest(10, 'c')
hits[hits['SearchPhrase'] != ''].groupby(['WatchID', 'ClientIP']).agg(c=('WatchID', 'size'), IsRefreshSum=('IsRefresh', 'sum'), AvgResolutionWidth=('ResolutionWidth', 'mean')).nlargest(10, 'c')
hits.groupby(['WatchID', 'ClientIP']).agg(c=('WatchID', 'size'), IsRefreshSum=('IsRefresh', 'sum'), AvgResolutionWidth=('ResolutionWidth', 'mean')).nlargest(10, 'c')
hits.groupby('URL').size().rename('c').nlargest(10).reset_index()
hits.groupby('URL').size().rename('c').nlargest(10).reset_index()
hits.assign(**{f'ClientIP_minus_{i}': hits['ClientIP'] - i for i in range(1, 4)}).groupby(['ClientIP', 'ClientIP_minus_1', 'ClientIP_minus_2', 'ClientIP_minus_3']).size().rename('c').nlargest(10).reset_index()
hits[(hits['CounterID'] == 62) & (hits['EventDate'] >= '2013-07-01') & (hits['EventDate'] <= '2013-07-31') & (hits['DontCountHits'] == 0) & (hits['IsRefresh'] == 0) & (hits['URL'] != '')].groupby('URL').size().nlargest(10)
hits[(hits['CounterID'] == 62) & (hits['EventDate'] >= '2013-07-01') & (hits['EventDate'] <= '2013-07-31') & (hits['DontCountHits'] == 0) & (hits['IsRefresh'] == 0) & (hits['Title'] != '')].groupby('Title').size().nlargest(10)
hits[(hits['CounterID'] == 62) & (hits['EventDate'] >= '2013-07-01') & (hits['EventDate'] <= '2013-07-31') & (hits['IsRefresh'] == 0) & (hits['IsLink'] != 0) & (hits['IsDownload'] == 0)].groupby('URL').size().rename('PageViews').nlargest(1010).reset_index().compute().iloc[1000:1010]
hits[(hits['CounterID'] == 62) & (hits['EventDate'] >= '2013-07-01') & (hits['EventDate'] <= '2013-07-31') & (hits['IsRefresh'] == 0)].assign(Src=lambda d: d['Referer'].where((d['SearchEngineID'] == 0) & (d['AdvEngineID'] == 0), '')).groupby(['TraficSourceID', 'SearchEngineID', 'AdvEngineID', 'Src', 'URL']).size().rename('PageViews').nlargest(1010).reset_index().compute().iloc[1000:1010]
hits[(hits['CounterID'] == 62) & (hits['EventDate'] >= '2013-07-01') & (hits['EventDate'] <= '2013-07-31') & (hits['IsRefresh'] == 0) & hits['TraficSourceID'].isin([-1, 6]) & (hits['RefererHash'] == 3594120000172545465)].groupby(['URLHash', 'EventDate']).size().rename('PageViews').nlargest(110).reset_index().compute().iloc[100:110]
hits[(hits['CounterID'] == 62) & (hits['EventDate'] >= '2013-07-01') & (hits['EventDate'] <= '2013-07-31') & (hits['IsRefresh'] == 0) & (hits['DontCountHits'] == 0) & (hits['URLHash'] == 2868770270353813622)].groupby(['WindowClientWidth', 'WindowClientHeight']).size().rename('PageViews').nlargest(10010).reset_index().compute().iloc[10000:10010]
hits[(hits['CounterID'] == 62) & (hits['EventDate'] >= '2013-07-14') & (hits['EventDate'] <= '2013-07-15') & (hits['IsRefresh'] == 0) & (hits['DontCountHits'] == 0)].assign(M=lambda d: d['EventTime'].dt.floor('min')).groupby('M').size().rename('PageViews').reset_index().compute().sort_values('M').iloc[1000:1010]
28 changes: 28 additions & 0 deletions dask/query
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash
# Reads a query from stdin, dispatches to the running in-VM server.
# Stdout: result (rendered table or scalar from the server).
# Stderr: query runtime in fractional seconds on the last line.
# Exit non-zero on error.
set -e

query=$(cat)

tmp=$(mktemp)
status=$(curl -sS -o "$tmp" -w '%{http_code}' \
-X POST --data-binary @- http://127.0.0.1:8000/query <<<"$query")

body=$(cat "$tmp")
rm -f "$tmp"

if [ "$status" != "200" ]; then
echo "query failed: HTTP $status: $body" >&2
exit 1
fi

# Pull `result` for stdout and `elapsed` for stderr (host timing protocol).
python3 - "$body" <<'PY'
import json, sys
d = json.loads(sys.argv[1])
print(d.get("result", ""))
sys.stderr.write(str(d["elapsed"]) + "\n")
PY
60 changes: 60 additions & 0 deletions dask/results/20260723/c6a.metal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"system": "Dask (DataFrame)",
"date": "2026-07-23",
"machine": "c6a.metal",
"cluster_size": 1,
"proprietary": "no",
"hardware": "cpu",
"tuned": "no",
"tags": ["Python","dataframe","in-memory","column-oriented","lukewarm-cold-run"],
"load_time": 40,
"data_size": 174168110180,
"concurrent_qps": 0.082,
"concurrent_error_ratio": 0.155,
"result": [
[64.222, 7.563, 7.727],
[58.304, 0.71, 0.707],
[57.661, 0.409, 0.254],
[57.432, 0.278, 0.257],
[58.667, 1.227, 1.162],
[59.447, 2.335, 2.309],
[57.666, 0.256, 0.311],
[58.037, 0.719, 0.758],
[59.549, 2.382, 2.306],
[null, null, null],
[67.082, 10.4, 9.805],
[68.578, 11.581, 11.438],
[61.524, 4.222, 4.296],
[67.714, 9.871, 11.01],
[113.814, 53.797, 54.739],
[59.166, 1.54, 1.588],
[142.554, 90.388, 88.26],
[64.71, 7.225, 7.211],
[136.769, 71.584, 68.834],
[57.715, 0.58, 0.514],
[null, null, null],
[null, null, null],
[null, null, null],
[null, null, null],
[58.351, 0.89, 0.948],
[null, null, null],
[63.587, 6.332, 6.151],
[60.525, 3.193, 3.226],
[null, null, null],
[61.464, 4.507, 4.705],
[71.409, 13.903, 14.178],
[209.28, 153.635, 153.406],
[208.328, 155.147, 154.055],
[69.802, 12.435, 12.374],
[69.473, 12.61, 12.722],
[76.846, 20.591, 20.255],
[59.272, 1.771, 2.214],
[59.065, 1.468, 1.418],
[58.574, 0.849, 0.917],
[61.266, 3.688, 3.947],
[58.726, 1.01, 1.018],
[58.432, 0.918, 0.903],
[58.448, 0.932, 0.923]
]
}

60 changes: 60 additions & 0 deletions dask/results/20260724/c6a.metal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"system": "Dask (DataFrame)",
"date": "2026-07-24",
"machine": "c6a.metal",
"cluster_size": 1,
"proprietary": "no",
"hardware": "cpu",
"tuned": "no",
"tags": ["Python","dataframe","in-memory","column-oriented","lukewarm-cold-run"],
"load_time": 71,
"data_size": 174168110180,
"concurrent_qps": 0.08,
"concurrent_error_ratio": 0.172,
"result": [
[64.327, 7.488, 7.706],
[58.413, 0.784, 0.911],
[57.779, 0.421, 0.251],
[57.608, 0.277, 0.276],
[58.342, 1.256, 1.233],
[59.416, 1.898, 2.104],
[57.507, 0.288, 0.287],
[57.919, 0.729, 0.703],
[60.01, 2.351, 2.709],
[null, null, null],
[67.568, 10.112, 10.153],
[68.678, 11.419, 11.295],
[61.52, 4.124, 4.377],
[67.667, 10.49, 10.105],
[105.971, 52.709, 54.968],
[58.969, 1.561, 1.493],
[141.452, 96.276, 86.095],
[64.34, 7.333, 6.791],
[134.602, 71.966, 75.828],
[57.882, 0.556, 0.475],
[null, null, null],
[null, null, null],
[null, null, null],
[null, null, null],
[58.34, 0.908, 0.868],
[null, null, null],
[63.947, 6.158, 6.867],
[61.09, 3.037, 3.529],
[null, null, null],
[61.51, 4.562, 4.68],
[71.334, 14.211, 13.895],
[209.84, 152.482, 154.958],
[209.852, 154.998, 151.511],
[69.724, 11.831, 12.081],
[69.544, 12.503, 12.443],
[77.534, 19.754, 20.131],
[59.624, 1.754, 2.013],
[58.879, 1.275, 1.494],
[58.487, 0.936, 0.879],
[61.248, 3.826, 3.788],
[58.826, 1.12, 1.043],
[58.374, 1.048, 0.831],
[58.59, 1.009, 0.974]
]
}

60 changes: 60 additions & 0 deletions dask/results/20260724/c7a.metal-48xl.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"system": "Dask (DataFrame)",
"date": "2026-07-24",
"machine": "c7a.metal-48xl",
"cluster_size": 1,
"proprietary": "no",
"hardware": "cpu",
"tuned": "no",
"tags": ["Python","dataframe","in-memory","column-oriented","lukewarm-cold-run"],
"load_time": 69,
"data_size": 174168110180,
"concurrent_qps": 0.092,
"concurrent_error_ratio": 0.167,
"result": [
[64.311, 6.044, 6.273],
[58.61, 0.59, 0.584],
[57.611, 0.287, 0.244],
[57.14, 0.225, 0.216],
[58.022, 1.115, 1.018],
[59.562, 1.782, 1.591],
[57.425, 0.241, 0.22],
[57.787, 0.545, 0.563],
[58.246, 1.871, 1.906],
[null, null, null],
[66.509, 9.188, 9.383],
[67.914, 10.232, 10.365],
[61.034, 3.578, 3.719],
[66.957, 9.32, 9.115],
[102.899, 47.573, 47.836],
[58.648, 1.288, 1.311],
[140.049, 91.377, 83.673],
[63.275, 6.373, 6.311],
[132.172, 71.46, 68.367],
[57.783, 0.454, 0.388],
[null, null, null],
[null, null, null],
[null, null, null],
[null, null, null],
[57.919, 0.823, 0.774],
[null, null, null],
[62.798, 5.355, 5.517],
[59.995, 2.525, 2.717],
[null, null, null],
[60.473, 3.712, 3.754],
[71.95, 14.743, 14.428],
[231.807, 174.428, 176.522],
[233.801, 173.07, 177.225],
[68.069, 11.209, 11.097],
[67.907, 11.658, 11.041],
[78.273, 20.86, 20.238],
[58.939, 1.52, 1.522],
[58.652, 1.115, 1.019],
[58.262, 0.761, 0.632],
[60.146, 3.115, 3.207],
[58.084, 0.778, 0.782],
[58.284, 0.8, 0.616],
[58.039, 0.824, 0.764]
]
}

60 changes: 60 additions & 0 deletions dask/results/20260724/c8g.metal-48xl.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"system": "Dask (DataFrame)",
"date": "2026-07-24",
"machine": "c8g.metal-48xl",
"cluster_size": 1,
"proprietary": "no",
"hardware": "cpu",
"tuned": "no",
"tags": ["Python","dataframe","in-memory","column-oriented","lukewarm-cold-run"],
"load_time": 69,
"data_size": 174168110180,
"concurrent_qps": 0.108,
"concurrent_error_ratio": 0.156,
"result": [
[62.696, 4.739, 4.583],
[58.581, 0.485, 0.484],
[58.325, 0.204, 0.193],
[56.962, 0.143, 0.165],
[57.693, 0.798, 0.808],
[58.185, 1.346, 1.292],
[56.986, 0.135, 0.136],
[57.324, 0.426, 0.424],
[58.487, 1.599, 1.616],
[null, null, null],
[63.786, 6.839, 6.854],
[64.769, 7.835, 7.924],
[60.103, 3.324, 3.296],
[63.45, 6.64, 6.689],
[94.583, 37.84, 37.699],
[57.987, 1.127, 1.113],
[120.212, 62.556, 62.337],
[61.859, 5.143, 5.089],
[112.079, 52.355, 53.691],
[57.159, 0.382, 0.326],
[null, null, null],
[null, null, null],
[null, null, null],
[null, null, null],
[57.604, 0.577, 0.581],
[null, null, null],
[61.807, 4.925, 4.442],
[59.267, 2.134, 2.08],
[null, null, null],
[59.457, 2.794, 2.899],
[66.703, 9.836, 9.601],
[162.965, 107.044, 106.46],
[163.732, 108.041, 107.67],
[66.84, 9.45, 9.142],
[66.628, 9.691, 9.656],
[70.519, 13.682, 13.813],
[58.274, 1.192, 1.231],
[57.728, 0.773, 0.794],
[57.567, 0.571, 0.59],
[59.564, 2.546, 2.64],
[57.742, 0.658, 0.658],
[68.956, 0.713, 0.62],
[57.639, 0.586, 0.64]
]
}

Loading