diff --git a/lib/download-hits-json b/lib/download-hits-json new file mode 100644 index 0000000000..5ae1404b51 --- /dev/null +++ b/lib/download-hits-json @@ -0,0 +1,13 @@ +#!/bin/bash +# Standalone version: the ClickBench Playground bakes a pre-decompressed +# hits.json into /opt/clickbench/datasets_ro and symlinks to it here. Outside +# the Playground that path doesn't exist, and parseable/load already falls +# back to downloading+decompressing hits.json.gz itself, so this script is a +# no-op there. Kept as a stub only so bench_download() has something to call. +set -e +if [ -d /opt/clickbench/datasets_ro ]; then + dir="${1:-.}" + mkdir -p "$dir" + cd "$dir" + ln -sf /opt/clickbench/datasets_ro/hits.json hits.json +fi \ No newline at end of file diff --git a/parseable/benchmark.sh b/parseable/benchmark.sh index 535701276c..861bf8055d 100755 --- a/parseable/benchmark.sh +++ b/parseable/benchmark.sh @@ -1,3 +1,4 @@ #!/bin/bash export BENCH_DOWNLOAD_SCRIPT="download-hits-json" +chmod +x ../lib/download-hits-json exec ../lib/benchmark-common.sh diff --git a/parseable/data-size b/parseable/data-size index 559b25d677..134b52d960 100755 --- a/parseable/data-size +++ b/parseable/data-size @@ -1,4 +1,4 @@ #!/bin/bash set -eu -du -bcs local-store | grep total | awk '{print $1}' +du -bcs data | grep total | awk '{print $1}' diff --git a/parseable/install b/parseable/install index 2d61f7ead5..3d39a979d7 100755 --- a/parseable/install +++ b/parseable/install @@ -13,7 +13,7 @@ if [ ! -x ./parseable ]; then # v2.7.2 fixes the inference; verified locally end-to-end against # the bundled static_schema.json and hits.json. wget --continue --progress=dot:giga \ - https://github.com/parseablehq/parseable/releases/download/v2.7.2/Parseable_OSS_x86_64-unknown-linux-gnu + https://github.com/parseablehq/parseable/releases/download/v3.0.0/Parseable_OSS_x86_64-unknown-linux-gnu mv Parseable_OSS_x86_64-unknown-linux-gnu parseable chmod +x parseable fi diff --git a/parseable/load b/parseable/load index 5cf60065f3..715f786f58 100755 --- a/parseable/load +++ b/parseable/load @@ -51,8 +51,14 @@ fi # subsequent chunk fails. 3 × 1000 lines is ~4x lower peak pressure # and empirically clears without 408s. curl --retry survives short # stalls so a briefly-saturated parseable doesn't fail the load. -LINES_PER_CHUNK=1000 -INGEST_JOBS=3 +NUM_CORES=$(nproc) +if [ "$NUM_CORES" -ge 190 ]; then + LINES_PER_CHUNK=2500 + INGEST_JOBS=20 +else + LINES_PER_CHUNK=1000 + INGEST_JOBS=3 +fi pv hits.json | parallel --pipe -N$LINES_PER_CHUNK --block 10M \ --jobs "$INGEST_JOBS" --halt-on-error 0 ' awk "BEGIN{print \"[\"} NR>1{print prev \",\"} {prev=\$0} END{if (prev) print prev; print \"]\"}" | diff --git a/parseable/query b/parseable/query index 34df5b8085..e468aeea20 100755 --- a/parseable/query +++ b/parseable/query @@ -7,16 +7,44 @@ set -e query=$(cat) -# Parseable filters every query by [startTime, endTime] against the -# row's ingest timestamp. The original benchmark used today's calendar -# day, which only works if the dataset was loaded today. In the -# playground the data is ingested during initial provisioning and -# then frozen into a snapshot, so "today" from the query script's -# point of view drifts past the load day and every row falls outside -# the window → all queries return zero. Use a wide window that -# covers any plausible load + query date. -START_TIME="2000-01-01T00:00:00.000Z" -END_TIME="2099-12-31T23:59:00.000Z" +# Derive Parseable's mandatory query window from the stream itself. Keep a +# five-minute margin so events exactly at either reported boundary are not +# lost to timestamp precision or boundary semantics. This lookup happens +# before the query timer starts. +stream_info=$(curl -sS --fail-with-body \ + -u "admin:admin" 'http://localhost:8000/api/v1/logstream/hits/info') + +mapfile -t time_range < <( + printf '%s' "$stream_info" | python3 -c ' +import json +import sys +from datetime import datetime, timedelta, timezone + +info = json.load(sys.stdin) + +def parse_timestamp(field): + value = info.get(field) + if not value: + raise ValueError(f"stream info has no {field}") + return datetime.fromisoformat(value.replace("Z", "+00:00")).astimezone(timezone.utc) + +def format_timestamp(value): + return value.isoformat(timespec="milliseconds").replace("+00:00", "Z") + +print(format_timestamp(parse_timestamp("firstEventAt") - timedelta(minutes=5))) +print(format_timestamp(parse_timestamp("latestEventAt") + timedelta(minutes=5))) +' +) + +if [ "${#time_range[@]}" -ne 2 ]; then + echo "could not derive query time range from hits stream info" >&2 + exit 1 +fi + +START_TIME=${time_range[0]} +END_TIME=${time_range[1]} + +echo "==> query time range: $START_TIME .. $END_TIME" >&2 # JSON-escape quotes inside the query. escaped=$(printf '%s' "$query" | sed 's/"/\\"/g') diff --git a/parseable/results/20260818/c6a.4xlarge.json b/parseable/results/20260818/c6a.4xlarge.json new file mode 100644 index 0000000000..a9f24c92af --- /dev/null +++ b/parseable/results/20260818/c6a.4xlarge.json @@ -0,0 +1,60 @@ +{ + "system": "Parseable (Parquet, partitioned)", + "date": "2026-08-18", + "machine": "c6a.4xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["Rust","column-oriented","lukewarm-cold-run"], + "load_time": 4931, + "data_size": 14023558981, + "concurrent_qps": 0.88, + "concurrent_error_ratio": 0, + "result": [ + [0.477, 0.068, 0.065], + [0.321, 0.06, 0.059], + [0.79, 0.106, 0.118], + [1.036, 0.118, 0.112], + [1.148, 0.513, 0.509], + [1.569, 0.694, 0.72], + [0.313, 0.048, 0.042], + [0.353, 0.074, 0.076], + [1.626, 0.83, 0.861], + [2.234, 0.927, 0.954], + [1.317, 0.251, 0.242], + [1.35, 0.274, 0.276], + [1.66, 0.798, 0.795], + [3.182, 1.38, 1.373], + [1.651, 0.908, 0.946], + [1.324, 0.615, 0.673], + [3.065, 1.552, 1.539], + [2.96, 1.538, 1.536], + [5.412, 2.636, 2.649], + [0.672, 0.088, 0.09], + [9.009, 2, 1.995], + [10.67, 2.762, 2.698], + [15.419, 4.219, 4.185], + [13.271, 1.074, 0.873], + [3.111, 0.231, 0.255], + [1.422, 0.442, 0.428], + [3.458, 0.364, 0.324], + [9.095, 2.894, 2.867], + [9.497, 8.115, 8.389], + [0.872, 0.519, 0.5], + [3.284, 0.854, 0.884], + [6.862, 1.068, 1.086], + [5.168, 3.15, 3.153], + [9.669, 4.369, 4.466], + [9.658, 4.382, 4.402], + [1.489, 1.222, 1.184], + [0.584, 0.109, 0.114], + [0.514, 0.081, 0.071], + [0.541, 0.056, 0.057], + [0.703, 0.191, 0.189], + [0.492, 0.04, 0.038], + [0.482, 0.037, 0.035], + [0.476, 0.033, 0.031] +] + } + \ No newline at end of file