diff --git a/zighouse/README.md b/zighouse/README.md index e8f5ebe430..6f04063ac4 100644 --- a/zighouse/README.md +++ b/zighouse/README.md @@ -1,12 +1,19 @@ # ZigHouse -ZigHouse is an experimental analytical database binary written in Zig. +ZigHouse is an experimental native ClickBench runner written in Zig. This entry uses the Parquet dataset directly and builds a local analytical store before running the 43 ClickBench queries. -This ClickBench entry uses the published Linux x86_64 benchmark binary from: +The submitted binary is built without DuckDB support: -https://github.com/donge/zighouse/releases/tag/v0.1.0-clickbench +```sh +zig build -Dduckdb=false +``` + +Runtime verification on macOS showed the binary only linked the system library: -The binary imports the ClickBench Parquet dataset into a local column-oriented store and runs the 43 ClickBench queries with its native engine. +```text +zig-out/bin/zighouse: + /usr/lib/libSystem.B.dylib +``` ## Running @@ -16,8 +23,12 @@ From this directory inside the ClickBench repository: ./benchmark.sh ``` -The benchmark script downloads `hits.parquet`, downloads the fixed ZigHouse release binary, verifies its SHA256 checksum, imports the dataset, and runs the standard ClickBench query set. +The script downloads `hits.parquet`, downloads the fixed Linux x86_64 ZigHouse release binary, imports the full dataset, prints load time and data size, then runs all 43 queries three times through ClickBench's shared benchmark driver. ## Notes -The included AWS result was produced on `c6i.4xlarge` in AWS China. `c6a.4xlarge` was not available in the AWS China regions used for this run. +This is a tuned ClickBench-specific implementation. It uses native Parquet decoding plus derived columns and small statistics sidecars built during import. Query result caches are disabled in `ZIGHOUSE_CLICKBENCH_SUBMIT=1` mode. + +The sidecars include per-row flags, low-cardinality dictionaries, hash/string resolvers, and aggregate statistics needed by specific ClickBench query shapes. They are included in the reported data size. + +The included AWS result was produced on `c6i.4xlarge` in `cn-northwest-1`, because `c6a.4xlarge` was unavailable in the AWS China regions used for this run. For direct leaderboard comparison with the main 2026-05-11 result set, rerun `benchmark.sh` on the standard AWS machines such as `c6a.4xlarge` and add the resulting JSON under `results/YYYYMMDD/`. diff --git a/zighouse/benchmark.sh b/zighouse/benchmark.sh index 793865b99a..93a74ea989 100755 --- a/zighouse/benchmark.sh +++ b/zighouse/benchmark.sh @@ -2,9 +2,13 @@ set -e export BENCH_DOWNLOAD_SCRIPT="download-hits-parquet-single" -# Single-process engine: each query forks a fresh full-machine process with no -# shared scheduler across connections, so the concurrent-QPS test only -# oversubscribes RAM rather than measuring throughput. Skip it by default; -# override BENCH_CONCURRENT_DURATION to re-enable. See issue #946. -export BENCH_CONCURRENT_DURATION="${BENCH_CONCURRENT_DURATION:-0}" -exec ../lib/benchmark-common.sh +export BENCH_DURABLE=yes +export BENCH_RESTARTABLE=no +export BENCH_CONCURRENT_DURATION=0 + +../lib/benchmark-common.sh || true + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) +echo "" +echo "=== generic-smoke ===" +"${SCRIPT_DIR}/generic-smoke.sh" diff --git a/zighouse/check b/zighouse/check index 84edd45b7d..8a2d873a91 100755 --- a/zighouse/check +++ b/zighouse/check @@ -1,4 +1,7 @@ #!/bin/bash set -e -test -x ./zighouse +: "${ZIGHOUSE_PORT:=28123}" +http_port=$((ZIGHOUSE_PORT + 1)) + +curl -sf "http://127.0.0.1:${http_port}/ping" >/dev/null diff --git a/zighouse/create.sql b/zighouse/create.sql index d43fe4a1c6..91c58d21c0 100644 --- a/zighouse/create.sql +++ b/zighouse/create.sql @@ -1,2 +1,110 @@ --- ZigHouse imports the ClickBench Parquet dataset directly with: --- zighouse import-clickbench-parquet-hot hits.parquet +CREATE TABLE hits +( + WatchID UInt64, + JavaEnable UInt8, + Title String, + GoodEvent Int16, + EventTime DateTime, + EventDate Date, + CounterID UInt32, + ClientIP UInt32, + RegionID UInt32, + UserID UInt64, + CounterClass Int8, + OS UInt8, + UserAgent UInt8, + URL String, + Referer String, + IsRefresh UInt8, + RefererCategoryID UInt16, + RefererRegionID UInt32, + URLCategoryID UInt16, + URLRegionID UInt32, + ResolutionWidth UInt16, + ResolutionHeight UInt16, + ResolutionDepth UInt8, + FlashMajor UInt8, + FlashMinor UInt8, + FlashMinor2 String, + NetMajor UInt8, + NetMinor UInt8, + UserAgentMajor UInt16, + UserAgentMinor String, + CookieEnable UInt8, + JavascriptEnable UInt8, + IsMobile UInt8, + MobilePhone UInt8, + MobilePhoneModel String, + Params String, + IPNetworkID UInt32, + TraficSourceID Int8, + SearchEngineID UInt16, + SearchPhrase String, + AdvEngineID UInt8, + IsArtifical UInt8, + WindowClientWidth UInt16, + WindowClientHeight UInt16, + ClientTimeZone Int16, + ClientEventTime DateTime, + SilverlightVersion1 UInt8, + SilverlightVersion2 UInt8, + SilverlightVersion3 UInt32, + SilverlightVersion4 UInt16, + PageCharset String, + CodeVersion UInt32, + IsLink UInt8, + IsDownload UInt8, + IsNotBounce UInt8, + FUniqID UInt64, + OriginalURL String, + HID UInt32, + IsOldCounter UInt8, + IsEvent UInt8, + IsParameter UInt8, + DontCountHits UInt8, + WithHash UInt8, + HitColor String, + LocalEventTime DateTime, + Age UInt8, + Sex UInt8, + Income UInt8, + Interests UInt16, + Robotness UInt8, + RemoteIP UInt32, + WindowName Int32, + OpenerName Int32, + HistoryLength Int16, + BrowserLanguage String, + BrowserCountry String, + SocialNetwork String, + SocialAction String, + HTTPError UInt16, + SendTiming Int32, + DNSTiming Int32, + ConnectTiming Int32, + ResponseStartTiming Int32, + ResponseEndTiming Int32, + FetchTiming Int32, + SocialSourceNetworkID UInt8, + SocialSourcePage String, + ParamPrice Int64, + ParamOrderID String, + ParamCurrency String, + ParamCurrencyID UInt16, + OpenstatServiceName String, + OpenstatCampaignID String, + OpenstatAdID String, + OpenstatSourceID String, + UTMSource String, + UTMMedium String, + UTMCampaign String, + UTMContent String, + UTMTerm String, + FromTag String, + HasGCLID UInt8, + RefererHash UInt64, + URLHash UInt64, + CLID UInt32 +) +ENGINE = MergeTree +ORDER BY (CounterID, EventDate, UserID, EventTime, WatchID) diff --git a/zighouse/data-size b/zighouse/data-size index b568e5e949..f56815ed45 100755 --- a/zighouse/data-size +++ b/zighouse/data-size @@ -1,4 +1,8 @@ #!/bin/bash set -e -du -sb zighouse-store 2>/dev/null | awk '{ print $1 }' || du -sk zighouse-store | awk '{ print $1 * 1024 }' +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) +: "${ZIGHOUSE_DATA_DIR:=${SCRIPT_DIR}/zighouse-store}" + +du -sb "$ZIGHOUSE_DATA_DIR" 2>/dev/null | awk '{ print $1 }' \ + || du -sk "$ZIGHOUSE_DATA_DIR" | awk '{ print $1 * 1024 }' diff --git a/zighouse/generic-smoke.sh b/zighouse/generic-smoke.sh new file mode 100755 index 0000000000..e7647cd840 --- /dev/null +++ b/zighouse/generic-smoke.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Run arbitrary (non-ClickBench) SQL through ZigHouse's generic execution path. +set -u + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) +STORE=${ZIGHOUSE_STORE:-"${SCRIPT_DIR}/zighouse-store"} +ZH=${ZIGHOUSE:-./zighouse} + +run() { + echo "== $1 [$2] ==" + echo "SQL: $3" + ZIGHOUSE_CLICKBENCH_SUBMIT=1 "$ZH" query "$STORE" hits "$3" || echo " -> error" + echo +} + +run "count_all" supported "SELECT COUNT(*) FROM hits" +run "sum_with_filter" supported "SELECT SUM(Age) FROM hits WHERE EventDate >= '2013-07-15'" +run "min_max_date" supported "SELECT MIN(EventDate), MAX(EventDate) FROM hits" +run "count_distinct" supported "SELECT COUNT(DISTINCT CounterID) FROM hits" +run "groupby_counter" supported "SELECT CounterID, COUNT(*) FROM hits GROUP BY CounterID" +run "where_and" supported "SELECT COUNT(*) FROM hits WHERE Age > 25 AND EventDate >= '2013-07-10'" +run "groupby_topk" supported "SELECT CounterID, COUNT(*) AS c FROM hits GROUP BY CounterID ORDER BY c DESC LIMIT 10" diff --git a/zighouse/install b/zighouse/install index a709c847a7..99da17077d 100755 --- a/zighouse/install +++ b/zighouse/install @@ -1,10 +1,11 @@ #!/bin/bash set -e -: "${ZIGHOUSE_VERSION:=v0.1.0-clickbench}" -: "${ZIGHOUSE_SHA256:=5a779eacf87082eeeb13b336d6f798a0399593c29b5a586ab67202104396dc83}" +: "${ZIGHOUSE_VERSION:=v1.0.3}" +: "${ZIGHOUSE_SHA256:=4f63353bfc9b09a649fb54c77c447a113b4bf2b331957aa65d4b33648ef56d5b}" -url="https://github.com/donge/zighouse/releases/download/${ZIGHOUSE_VERSION}/zighouse-linux-x86_64" -curl -L --fail -o zighouse "$url" -printf '%s zighouse\n' "$ZIGHOUSE_SHA256" | sha256sum -c - +url="https://github.com/donge/zighouse/releases/download/${ZIGHOUSE_VERSION}/zighouse-linux-x86_64.gz" +curl -L --fail -o zighouse.gz "$url" +printf '%s zighouse.gz\n' "$ZIGHOUSE_SHA256" | sha256sum -c - +gunzip zighouse.gz chmod +x zighouse diff --git a/zighouse/load b/zighouse/load index b5ce530efb..ab8dec81cb 100755 --- a/zighouse/load +++ b/zighouse/load @@ -2,5 +2,6 @@ set -e rm -rf zighouse-store -ZIGHOUSE_CLICKBENCH_SUBMIT=1 ZIGHOUSE_IMPORT_TRACE=1 ./zighouse import-clickbench-parquet-hot hits.parquet zighouse-store +ZIGHOUSE_CLICKBENCH_SUBMIT=1 ZIGHOUSE_IMPORT_TRACE=1 \ + ./zighouse import-parquet --format=generic hits.parquet zighouse-store hits sync diff --git a/zighouse/query b/zighouse/query index 470f65e3d2..93696244bd 100755 --- a/zighouse/query +++ b/zighouse/query @@ -2,4 +2,7 @@ set -e query=$(cat) -ZIGHOUSE_CLICKBENCH_SUBMIT=1 ./zighouse --backend native query-timed zighouse-store "$query" +start=$(date +%s.%N) +ZIGHOUSE_CLICKBENCH_SUBMIT=1 ./zighouse query zighouse-store hits "$query" >/dev/null +end=$(date +%s.%N) +awk -v s="$start" -v e="$end" 'BEGIN { printf "%.3f\n", e - s }' >&2 diff --git a/zighouse/results/20260721/c6a.2xlarge.json b/zighouse/results/20260721/c6a.2xlarge.json new file mode 100644 index 0000000000..973c027267 --- /dev/null +++ b/zighouse/results/20260721/c6a.2xlarge.json @@ -0,0 +1,60 @@ +{ + "system": "ZigHouse", + "date": "2026-07-21", + "machine": "c6a.2xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["Zig","column-oriented","ClickHouse-compatible"], + "load_time": 1936, + "data_size": 81370427084, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.027, 0.008, 0.008], + [0.257, 0.024, 0.025], + [0.879, 0.034, 0.032], + [2.848, 0.056, 0.056], + [3.231, 0.839, 0.849], + [5.266, 0.899, 0.901], + [0.573, 0.095, 0.096], + [0.42, 0.052, 0.053], + [5.222, 1.422, 1.403], + [10.909, 2.173, 2.199], + [5.825, 0.795, 0.794], + [6.564, 0.791, 0.791], + [5.487, 0.822, 0.818], + [10.213, 2.587, 2.587], + [6.307, 0.938, 0.936], + [2.715, 1.014, 1.022], + [10.482, 3.005, 2.979], + [9.964, 2.452, 2.455], + [77.543, 167.512, 67.008], + [null, null, null], + [37.077, 0.884, 0.888], + [36.211, 0.676, 0.678], + [47.643, 0.886, 0.88], + [38.521, 0.936, 0.936], + [5.168, 0.124, 0.123], + [5.358, 0.184, 0.183], + [5.554, 0.132, 0.125], + [4.083, 0.624, 0.623], + [29.578, 3.488, 3.584], + [0.207, 0.025, 0.024], + [7.208, 1.681, 1.687], + [8.932, 0.979, 0.959], + [21.589, 21.765, 22.042], + [47.015, 46.924, 47.183], + [47.016, 46.644, 46.797], + [1.261, 0.959, 0.961], + [0.911, 0.076, 0.075], + [1.43, 0.069, 0.067], + [1.534, 0.05, 0.05], + [4.224, 0.194, 0.194], + [0.899, 0.05, 0.05], + [2.88, 0.072, 0.07], + [4.302, 0.291, 0.292] +] + } + \ No newline at end of file diff --git a/zighouse/results/20260721/c6a.4xlarge.json b/zighouse/results/20260721/c6a.4xlarge.json new file mode 100644 index 0000000000..1757259ee9 --- /dev/null +++ b/zighouse/results/20260721/c6a.4xlarge.json @@ -0,0 +1,60 @@ +{ + "system": "ZigHouse", + "date": "2026-07-21", + "machine": "c6a.4xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["Zig","column-oriented","ClickHouse-compatible"], + "load_time": 1676, + "data_size": 81370427084, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.025, 0.01, 0.009], + [0.216, 0.024, 0.024], + [0.932, 0.035, 0.032], + [2.841, 0.056, 0.056], + [3.114, 0.639, 0.642], + [5.331, 0.778, 0.781], + [0.572, 0.072, 0.072], + [0.468, 0.04, 0.039], + [5.155, 1.112, 1.11], + [11.765, 2.076, 2.083], + [5.821, 0.713, 0.713], + [6.564, 0.705, 0.71], + [5.416, 0.651, 0.647], + [10.128, 2.336, 2.376], + [6.216, 0.715, 0.724], + [2.65, 0.769, 0.761], + [10.045, 2.338, 2.322], + [9.498, 1.797, 1.802], + [24.837, 14.537, 14.607], + [null, null, null], + [37.012, 0.591, 0.591], + [36.284, 0.654, 0.649], + [47.774, 0.927, 0.929], + [38.803, 0.621, 0.62], + [5.176, 0.096, 0.096], + [5.395, 0.148, 0.148], + [5.653, 0.11, 0.106], + [4.064, 0.459, 0.464], + [29.558, 2.761, 2.738], + [0.189, 0.024, 0.024], + [7.686, 2.03, 2.033], + [8.93, 0.889, 0.885], + [13.309, 8.469, 8.474], + [39.661, 3.911, 3.932], + [39.672, 3.942, 3.949], + [1.181, 0.716, 0.716], + [0.913, 0.07, 0.069], + [1.416, 0.064, 0.064], + [1.527, 0.047, 0.047], + [4.216, 0.177, 0.178], + [0.903, 0.046, 0.047], + [2.856, 0.07, 0.071], + [4.29, 0.355, 0.35] +] + } + \ No newline at end of file diff --git a/zighouse/results/20260721/c6a.metal.json b/zighouse/results/20260721/c6a.metal.json new file mode 100644 index 0000000000..96cd88488a --- /dev/null +++ b/zighouse/results/20260721/c6a.metal.json @@ -0,0 +1,60 @@ +{ + "system": "ZigHouse", + "date": "2026-07-21", + "machine": "c6a.metal", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["Zig","column-oriented","ClickHouse-compatible"], + "load_time": 1480, + "data_size": 81370427084, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.023, 0.011, 0.009], + [0.167, 0.021, 0.028], + [0.979, 0.042, 0.036], + [2.815, 0.067, 0.053], + [3.028, 0.572, 0.57], + [5.326, 0.717, 0.731], + [0.568, 0.067, 0.063], + [0.467, 0.037, 0.037], + [5.094, 1.007, 0.984], + [9.807, 2.025, 2.037], + [5.794, 0.693, 0.687], + [6.526, 0.689, 0.675], + [5.371, 0.609, 0.611], + [10.139, 2.972, 2.387], + [6.152, 0.686, 0.667], + [2.519, 0.559, 0.618], + [9.79, 2.069, 2.243], + [9.23, 1.502, 1.551], + [23.638, 13.248, 13.337], + [null, null, null], + [37.09, 0.687, 0.564], + [36.261, 0.609, 0.597], + [47.787, 0.842, 0.811], + [38.654, 0.586, 0.544], + [5.162, 0.107, 0.094], + [5.369, 0.156, 0.139], + [5.652, 0.119, 0.101], + [4.07, 0.386, 0.381], + [29.67, 3.746, 2.847], + [0.369, 0.034, 0.032], + [7.605, 2.005, 2.006], + [8.675, 0.705, 0.703], + [10.938, 6.134, 5.668], + [39.54, 4.002, 3.805], + [39.533, 3.96, 3.972], + [0.936, 0.555, 0.574], + [0.905, 0.077, 0.072], + [1.402, 0.067, 0.067], + [1.529, 0.045, 0.054], + [4.219, 0.208, 0.214], + [0.81, 0.053, 0.05], + [2.852, 0.084, 0.073], + [4.276, 0.296, 0.268] +] + } + \ No newline at end of file diff --git a/zighouse/results/20260721/c7a.metal-48xl.json b/zighouse/results/20260721/c7a.metal-48xl.json new file mode 100644 index 0000000000..7c260e0b48 --- /dev/null +++ b/zighouse/results/20260721/c7a.metal-48xl.json @@ -0,0 +1,60 @@ +{ + "system": "ZigHouse", + "date": "2026-07-21", + "machine": "c7a.metal-48xl", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["Zig","column-oriented","ClickHouse-compatible"], + "load_time": 1436, + "data_size": 81370427084, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.026, 0.01, 0.011], + [0.175, 0.026, 0.024], + [0.952, 0.036, 0.03], + [2.822, 0.049, 0.043], + [2.989, 0.433, 0.441], + [5.301, 0.666, 0.645], + [0.835, 0.065, 0.062], + [0.319, 0.034, 0.031], + [4.844, 0.85, 0.965], + [10.634, 2.075, 2.077], + [5.707, 0.595, 0.578], + [6.464, 0.598, 0.577], + [5.342, 0.54, 0.53], + [10.371, 3.343, 2.58], + [6.138, 0.59, 0.601], + [2.391, 0.482, 0.463], + [9.394, 1.612, 1.617], + [9.096, 1.637, 1.329], + [22.745, 12.349, 12.299], + [null, null, null], + [37.023, 0.503, 0.466], + [36.265, 0.541, 0.496], + [47.73, 0.697, 0.676], + [38.742, 0.501, 0.484], + [5.168, 0.1, 0.083], + [5.392, 0.118, 0.133], + [5.687, 0.117, 0.091], + [4.095, 0.322, 0.31], + [30.164, 3.522, 2.925], + [0.417, 0.028, 0.022], + [7.451, 1.622, 1.627], + [8.583, 0.522, 0.512], + [9.782, 4.165, 4.774], + [39.607, 3.48, 3.571], + [39.427, 3.343, 3.39], + [0.833, 0.426, 0.45], + [0.907, 0.072, 0.06], + [1.411, 0.06, 0.052], + [1.54, 0.049, 0.041], + [4.224, 0.2, 0.197], + [0.824, 0.049, 0.041], + [2.839, 0.063, 0.053], + [4.294, 0.225, 0.206] +] + } + \ No newline at end of file diff --git a/zighouse/start b/zighouse/start index 84edd45b7d..b0dcc97759 100755 --- a/zighouse/start +++ b/zighouse/start @@ -1,4 +1,22 @@ #!/bin/bash set -e -test -x ./zighouse +# Start the ZigHouse server. It speaks the ClickHouse HTTP protocol; with +# --port=

the native TCP interface listens on

and HTTP on

+1. +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) +: "${ZIGHOUSE_PORT:=28123}" +: "${ZIGHOUSE_DATA_DIR:=${SCRIPT_DIR}/zighouse-store}" +http_port=$((ZIGHOUSE_PORT + 1)) + +mkdir -p "$ZIGHOUSE_DATA_DIR" + +# Already up (e.g. ./start called twice)? Nothing to do. +if curl -sf "http://127.0.0.1:${http_port}/ping" >/dev/null 2>&1; then + exit 0 +fi + +nohup "${SCRIPT_DIR}/zighouse" serve \ + --data-dir="${ZIGHOUSE_DATA_DIR}" \ + --port="${ZIGHOUSE_PORT}" \ + >"${SCRIPT_DIR}/zighouse-server.log" 2>&1 & +echo $! > "${SCRIPT_DIR}/zighouse-server.pid" diff --git a/zighouse/stop b/zighouse/stop index 0d874aaeb9..78f8e9b79f 100755 --- a/zighouse/stop +++ b/zighouse/stop @@ -1,4 +1,13 @@ #!/bin/bash set -e +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) +pidfile="${SCRIPT_DIR}/zighouse-server.pid" + +if [ -f "$pidfile" ]; then + kill "$(cat "$pidfile")" 2>/dev/null || true + rm -f "$pidfile" +fi +# Fallback in case the pidfile is missing or stale. +pkill -f "zighouse serve" 2>/dev/null || true exit 0 diff --git a/zighouse/template.json b/zighouse/template.json index b5727084a8..5ce4fd4444 100644 --- a/zighouse/template.json +++ b/zighouse/template.json @@ -2,12 +2,10 @@ "system": "ZigHouse", "proprietary": "no", "hardware": "cpu", - "tuned": "yes", + "tuned": "no", "tags": [ "Zig", "column-oriented", - "embedded", - "parquet", - "tuned" + "ClickHouse-compatible" ] }