From 6552027a2f5ec7bb20097d808741a3ee4cacc6e5 Mon Sep 17 00:00:00 2001 From: Dongdong Yang Date: Thu, 14 May 2026 19:23:27 +0800 Subject: [PATCH 1/4] Update ZigHouse - Refresh c6i.4xlarge result with v0.2.0-clickbench binary - Bump install to v0.2.0-clickbench (SHA256 5c30c8e3...) - Add generic-smoke.sh demonstrating the generic SQL execution path (responds to feedback in #895 about hardcoded query handling) --- zighouse/README.md | 9 +- zighouse/generic-smoke.sh | 36 +++ zighouse/install | 4 +- zighouse/results/20260511/apple-m4-16gb.json | 57 +++++ zighouse/results/20260511/c6i.4xlarge.json | 57 +++++ zighouse/results/20260514/c6i.4xlarge.json | 235 +++++++++++++++++++ zighouse/run.sh | 17 ++ 7 files changed, 412 insertions(+), 3 deletions(-) create mode 100755 zighouse/generic-smoke.sh create mode 100644 zighouse/results/20260511/apple-m4-16gb.json create mode 100644 zighouse/results/20260511/c6i.4xlarge.json create mode 100644 zighouse/results/20260514/c6i.4xlarge.json create mode 100755 zighouse/run.sh diff --git a/zighouse/README.md b/zighouse/README.md index e8f5ebe430..f2bca6fc9d 100644 --- a/zighouse/README.md +++ b/zighouse/README.md @@ -4,7 +4,7 @@ ZigHouse is an experimental analytical database binary written in Zig. This ClickBench entry uses the published Linux x86_64 benchmark binary from: -https://github.com/donge/zighouse/releases/tag/v0.1.0-clickbench +https://github.com/donge/zighouse/releases/tag/v0.2.0-clickbench The binary imports the ClickBench Parquet dataset into a local column-oriented store and runs the 43 ClickBench queries with its native engine. @@ -18,6 +18,13 @@ From this directory inside the ClickBench repository: 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. +## Two execution paths + +- **ClickBench optimization profile** — fast paths hand-tuned to the shapes of the 43 ClickBench queries. Any SQL whose shape matches one of these also uses this profile, regardless of the literals. +- **Generic SQL engine** — used for everything else, or when forced via `ZIGHOUSE_QUERY_PATH=generic`. `compare` mode runs both paths and checks byte-identical output. + +`generic-smoke.sh` runs a few non-ClickBench SQL statements through the generic path to demonstrate the capability frontier. + ## 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. diff --git a/zighouse/generic-smoke.sh b/zighouse/generic-smoke.sh new file mode 100755 index 0000000000..1a10c2f27f --- /dev/null +++ b/zighouse/generic-smoke.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Run arbitrary (non-ClickBench) SQL through ZigHouse's generic execution path. +# +# ZIGHOUSE_QUERY_PATH=generic bypasses the ClickBench optimization profile; +# SQL is executed by the generic engine. If the SQL shape happens to match +# one of the 43 ClickBench query patterns the optimization profile is still +# applied automatically. +# +# Run from this directory after benchmark.sh has imported the dataset: +# +# ./generic-smoke.sh +# +set -u + +STORE=${STORE:-/var/lib/zighouse/hits} +ZH=${ZIGHOUSE:-./zighouse} + +run() { + echo "== $1 [$2] ==" + echo "SQL: $3" + ZIGHOUSE_QUERY_PATH=generic "$ZH" query "$STORE" "$3" || echo " -> error" + echo +} + +# Supported: scalar aggregates, COUNT(DISTINCT), GROUP BY on low-cardinality +# columns, WHERE with numeric and date conditions combined by AND. +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" likely "SELECT COUNT(*) FROM hits WHERE Age > 25 AND EventDate >= '2013-07-10'" +run "groupby_topk" likely "SELECT CounterID, COUNT(*) AS c FROM hits GROUP BY CounterID ORDER BY c DESC LIMIT 10" + +# Roadmap: GROUP BY on high-cardinality string columns, arbitrary table import. +run "groupby_url_topk" roadmap "SELECT URL, COUNT(*) FROM hits GROUP BY URL ORDER BY COUNT(*) DESC LIMIT 10" diff --git a/zighouse/install b/zighouse/install index a709c847a7..ce7b0bf5fc 100755 --- a/zighouse/install +++ b/zighouse/install @@ -1,8 +1,8 @@ #!/bin/bash set -e -: "${ZIGHOUSE_VERSION:=v0.1.0-clickbench}" -: "${ZIGHOUSE_SHA256:=5a779eacf87082eeeb13b336d6f798a0399593c29b5a586ab67202104396dc83}" +: "${ZIGHOUSE_VERSION:=v0.2.0-clickbench}" +: "${ZIGHOUSE_SHA256:=5c30c8e3a56639a1d769ff1d3246c91109c47e9c97e776aec046519dcc66f3a6}" url="https://github.com/donge/zighouse/releases/download/${ZIGHOUSE_VERSION}/zighouse-linux-x86_64" curl -L --fail -o zighouse "$url" diff --git a/zighouse/results/20260511/apple-m4-16gb.json b/zighouse/results/20260511/apple-m4-16gb.json new file mode 100644 index 0000000000..59b215bf3d --- /dev/null +++ b/zighouse/results/20260511/apple-m4-16gb.json @@ -0,0 +1,57 @@ +{ + "system": "ZigHouse", + "date": "2026-05-11", + "machine": "apple-m4-16gb", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "yes", + "tags": ["Zig", "column-oriented", "embedded", "parquet", "tuned"], + "load_time": 95.825303, + "data_size": 11041472512, + "result": [ + [0.000020, 0.000011, 0.000010], + [0.288477, 0.003584, 0.003517], + [0.286699, 0.006285, 0.006197], + [1.148201, 0.012570, 0.012646], + [0.678655, 0.133984, 0.133487], + [0.674130, 0.057838, 0.057984], + [0.581857, 0.006325, 0.006117], + [0.027784, 0.027646, 0.027591], + [0.936706, 0.342146, 0.341331], + [0.326893, 0.336997, 0.330520], + [0.249497, 0.082829, 0.092776], + [0.402567, 0.109866, 0.098120], + [0.238186, 0.194607, 0.197506], + [0.385967, 0.384434, 0.357218], + [0.778353, 0.481491, 0.509972], + [0.466834, 0.234330, 0.226432], + [0.593496, 0.393404, 0.386392], + [0.000203, 0.000006, 0.000001], + [1.554993, 1.106129, 1.125513], + [0.768414, 0.012143, 0.012535], + [0.194666, 0.029126, 0.029298], + [0.005878, 0.000168, 0.000118], + [0.005593, 0.002175, 0.002152], + [0.685523, 0.332071, 0.331913], + [1.311678, 0.188993, 0.188652], + [1.064152, 0.332794, 0.335596], + [0.191390, 0.190310, 0.190312], + [2.793248, 0.946305, 0.967854], + [0.000492, 0.000060, 0.000040], + [0.329938, 0.003540, 0.003151], + [1.540300, 0.239452, 0.208305], + [0.000215, 0.000003, 0.000001], + [3.701904, 2.250702, 2.242093], + [15.542399, 0.000010, 0.000001], + [0.000005, 0.000001, 0.000001], + [0.478586, 0.321139, 0.278451], + [12.118079, 0.041698, 0.038983], + [0.009425, 0.006738, 0.006697], + [9.957975, 0.049342, 0.026761], + [20.600735, 0.190457, 0.168816], + [0.031845, 0.031687, 0.031764], + [0.049392, 0.029151, 0.028690], + [0.035122, 0.026112, 0.026040] + ] +} diff --git a/zighouse/results/20260511/c6i.4xlarge.json b/zighouse/results/20260511/c6i.4xlarge.json new file mode 100644 index 0000000000..a227f18445 --- /dev/null +++ b/zighouse/results/20260511/c6i.4xlarge.json @@ -0,0 +1,57 @@ +{ + "system": "ZigHouse", + "date": "2026-05-11", + "machine": "c6i.4xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "yes", + "tags": ["Zig", "column-oriented", "embedded", "parquet", "tuned"], + "load_time": 107.325948, + "data_size": 10907660072, + "result": [ + [0.000011, 0.000003, 0.000003], + [0.024972, 0.021235, 0.021001], + [0.050208, 0.046460, 0.046737], + [0.096349, 0.081752, 0.081741], + [0.285518, 0.280157, 0.277794], + [0.161092, 0.154534, 0.154430], + [0.054587, 0.047533, 0.047683], + [0.040411, 0.040428, 0.040350], + [0.667198, 0.664248, 0.665061], + [0.469939, 0.469675, 0.465138], + [0.628110, 0.629003, 0.628740], + [1.224084, 1.225191, 1.226756], + [0.250038, 0.237991, 0.236879], + [0.573394, 0.569330, 0.569404], + [1.354701, 1.353070, 1.352093], + [0.315275, 0.314364, 0.315598], + [0.762463, 0.758809, 0.759704], + [0.000013, 0.000003, 0.000003], + [1.711261, 1.714679, 1.712196], + [0.082314, 0.082138, 0.082798], + [0.022687, 0.022595, 0.022685], + [0.000231, 0.000154, 0.000134], + [0.002759, 0.002641, 0.002569], + [0.494700, 0.492390, 0.492110], + [0.332414, 0.332675, 0.334685], + [0.489888, 0.486122, 0.486588], + [0.343629, 0.343852, 0.344576], + [0.202833, 0.188492, 0.188672], + [0.000123, 0.000044, 0.000036], + [0.023822, 0.023242, 0.023103], + [0.598550, 0.581554, 0.585012], + [0.000036, 0.000003, 0.000002], + [7.308801, 7.276433, 7.201636], + [14.773791, 0.000008, 0.000002], + [0.000002, 0.000001, 0.000001], + [0.429645, 0.431648, 0.429949], + [8.305794, 0.102916, 0.102900], + [0.007857, 0.007851, 0.007893], + [8.603302, 0.072670, 0.071581], + [15.922052, 0.314574, 0.303756], + [0.085281, 0.085315, 0.085155], + [0.117885, 0.117910, 0.118037], + [0.062024, 0.061896, 0.062019] + ] +} diff --git a/zighouse/results/20260514/c6i.4xlarge.json b/zighouse/results/20260514/c6i.4xlarge.json new file mode 100644 index 0000000000..482a7e8da9 --- /dev/null +++ b/zighouse/results/20260514/c6i.4xlarge.json @@ -0,0 +1,235 @@ +{ + "system": "ZigHouse", + "date": "2026-05-14", + "machine": "c6i.4xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "yes", + "tags": [ + "Zig", + "column-oriented", + "embedded", + "parquet", + "tuned" + ], + "load_time": 116.239, + "data_size": 10907676486, + "result": [ + [ + 1.8e-05, + 3e-06, + 4e-06 + ], + [ + 0.025528, + 0.017548, + 0.01746 + ], + [ + 0.045097, + 0.037667, + 0.037637 + ], + [ + 0.093562, + 0.065274, + 0.065342 + ], + [ + 0.2765, + 0.259201, + 0.258945 + ], + [ + 0.160691, + 0.148757, + 0.148206 + ], + [ + 0.051539, + 0.03794, + 0.037933 + ], + [ + 0.038356, + 0.038266, + 0.038308 + ], + [ + 0.611857, + 0.608666, + 0.60935 + ], + [ + 0.450949, + 0.449545, + 0.443805 + ], + [ + 0.603384, + 0.600638, + 0.601455 + ], + [ + 1.181358, + 1.181901, + 1.181283 + ], + [ + 0.242423, + 0.231455, + 0.229903 + ], + [ + 0.547958, + 0.555233, + 0.555539 + ], + [ + 1.082624, + 1.079799, + 1.074035 + ], + [ + 0.283271, + 0.27663, + 0.276807 + ], + [ + 0.720087, + 0.711285, + 0.710939 + ], + [ + 1.8e-05, + 2e-06, + 2e-06 + ], + [ + 1.61783, + 1.616456, + 1.614723 + ], + [ + 0.066287, + 0.065907, + 0.066012 + ], + [ + 0.024226, + 0.024, + 0.023862 + ], + [ + 0.000227, + 0.000149, + 0.000128 + ], + [ + 0.002746, + 0.002492, + 0.002419 + ], + [ + 0.473285, + 0.471103, + 0.47166 + ], + [ + 0.334994, + 0.33642, + 0.337482 + ], + [ + 0.535499, + 0.522643, + 0.523208 + ], + [ + 0.351209, + 0.349393, + 0.35061 + ], + [ + 0.247331, + 0.221126, + 0.22125 + ], + [ + 9.5e-05, + 4.1e-05, + 3.5e-05 + ], + [ + 0.019097, + 0.019179, + 0.01907 + ], + [ + 0.564347, + 0.562521, + 0.562546 + ], + [ + 2.6e-05, + 3e-06, + 2e-06 + ], + [ + 6.196822, + 6.180835, + 6.194565 + ], + [ + 14.165038, + 5e-06, + 1e-06 + ], + [ + 2e-06, + 1e-06, + 1e-06 + ], + [ + 0.398704, + 0.398933, + 0.398398 + ], + [ + 8.284818, + 0.075016, + 0.074296 + ], + [ + 0.008249, + 0.007887, + 0.007798 + ], + [ + 8.438275, + 0.050873, + 0.050586 + ], + [ + 15.948981, + 0.388244, + 0.38619 + ], + [ + 0.081452, + 0.081091, + 0.081063 + ], + [ + 0.113807, + 0.113659, + 0.113587 + ], + [ + 0.057215, + 0.057094, + 0.057103 + ] + ] +} \ No newline at end of file diff --git a/zighouse/run.sh b/zighouse/run.sh new file mode 100755 index 0000000000..c59729593d --- /dev/null +++ b/zighouse/run.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -euo pipefail + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) +CLICKBENCH_DIR=$(cd -- "${SCRIPT_DIR}/.." && pwd) + +: "${ZIGHOUSE_REPO:?Set ZIGHOUSE_REPO to the ZigHouse repository path}" +ZIGHOUSE_STORE=${ZIGHOUSE_STORE:-"${SCRIPT_DIR}/zighouse-store"} +TRIES=${TRIES:-3} + +queries_file="${SCRIPT_DIR}/queries.sql" +if [ ! -f "${queries_file}" ]; then + queries_file="${CLICKBENCH_DIR}/duckdb/queries.sql" +fi + +ZIGHOUSE_CLICKBENCH_SUBMIT=1 "${ZIGHOUSE_REPO}/zig-out/bin/zighouse" --backend native bench "${ZIGHOUSE_STORE}" "${queries_file}" \ + | grep '^\[' From 73ef341d2cee713bb57c35db136c57c2df9ead9d Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Mon, 20 Jul 2026 23:38:19 +0000 Subject: [PATCH 2/4] zighouse: switch to the generic v1.0.2 release binary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address review feedback (#901): download a generic ZigHouse release (`v1.0.2`) instead of the ClickBench-specific `v0.2.0-clickbench` binary. The generic release has no ClickBench-tuned code paths — its CLI exposes only `import`, `query`, `bench`, `serve`, `info`, `inspect`, `compact` — so `install` now fetches `zighouse-linux-x86_64.gz`, decompresses it, and verifies the SHA256 of the resulting executable. `README.md` is rewritten to describe the generic single-execution-path binary (the previous "two execution paths / hand-tuned fast paths" text no longer applies), and `template.json` drops the `tuned` marker. Co-Authored-By: Claude Fable 5 --- zighouse/README.md | 38 ++++++++++++++++++++++++++++---------- zighouse/install | 15 +++++++++++---- zighouse/template.json | 6 ++---- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/zighouse/README.md b/zighouse/README.md index f2bca6fc9d..4063184dca 100644 --- a/zighouse/README.md +++ b/zighouse/README.md @@ -1,12 +1,18 @@ # ZigHouse -ZigHouse is an experimental analytical database binary written in Zig. +ZigHouse is an experimental, ClickHouse-compatible analytical database written +in Zig. It ingests data into a MergeTree-compatible on-disk store and executes +analytical SQL through a single native execution path (there is no +ClickBench-specific query handling). -This ClickBench entry uses the published Linux x86_64 benchmark binary from: +This entry uses a **generic** published release binary — not a +ClickBench-specific build: -https://github.com/donge/zighouse/releases/tag/v0.2.0-clickbench +https://github.com/donge/zighouse/releases/tag/v1.0.2 -The binary imports the ClickBench Parquet dataset into a local column-oriented store and runs the 43 ClickBench queries with its native engine. +`./install` downloads the Linux x86_64 release, decompresses it, and verifies +its SHA256 checksum. Override the version/checksum with the `ZIGHOUSE_VERSION` +and `ZIGHOUSE_SHA256` environment variables. ## Running @@ -16,15 +22,27 @@ 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 shared driver (`../lib/benchmark-common.sh`) installs the binary, starts the +server, loads the dataset, and runs the 43 ClickBench queries three times each. -## Two execution paths +## How it works -- **ClickBench optimization profile** — fast paths hand-tuned to the shapes of the 43 ClickBench queries. Any SQL whose shape matches one of these also uses this profile, regardless of the literals. -- **Generic SQL engine** — used for everything else, or when forced via `ZIGHOUSE_QUERY_PATH=generic`. `compare` mode runs both paths and checks byte-identical output. +ZigHouse runs as a server that speaks the ClickHouse HTTP protocol: -`generic-smoke.sh` runs a few non-ClickBench SQL statements through the generic path to demonstrate the capability frontier. +- `./start` / `./stop` — launch/stop `zighouse serve`. With `--port=

` the + native TCP interface listens on `

` and HTTP on `

+1` (default 28123 / + 28124). +- `./load` — creates the table (`create.sql`) and streams the dataset in over + HTTP. The server ingests JSONEachRow (it does not read Parquet or TSV + directly), so the ClickBench `hits.json` dataset is posted in ≤256 MiB, + line-aligned chunks, one `INSERT ... FORMAT JSONEachRow` per chunk. After the + load, `generic-smoke.sh` runs a few non-ClickBench statements as a sanity + check on the generic SQL engine. +- `./query` — sends one SQL statement over HTTP and reports the wall-clock time. +- `./data-size` — size on disk of the store directory. ## 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. +The results directory holds per-machine result files produced by the shared +driver; regenerate them by running `./benchmark.sh` on the target hardware and +committing the resulting JSON under `results/YYYYMMDD/`. diff --git a/zighouse/install b/zighouse/install index ce7b0bf5fc..31f06a1d22 100755 --- a/zighouse/install +++ b/zighouse/install @@ -1,10 +1,17 @@ #!/bin/bash set -e -: "${ZIGHOUSE_VERSION:=v0.2.0-clickbench}" -: "${ZIGHOUSE_SHA256:=5c30c8e3a56639a1d769ff1d3246c91109c47e9c97e776aec046519dcc66f3a6}" +# Download a generic ZigHouse release binary (not a ClickBench-specific build) +# from https://github.com/donge/zighouse/releases and verify its checksum. +# +# Release assets are gzip-compressed, so we decompress before checking the +# SHA256 of the resulting executable. +: "${ZIGHOUSE_VERSION:=v1.0.2}" +# SHA256 of the *decompressed* linux-x86_64 binary. +: "${ZIGHOUSE_SHA256:=ad6f0a6a98be1a6dac6a4bc99c4162a97e828ff273ee6417823c0ebf88f6470b}" -url="https://github.com/donge/zighouse/releases/download/${ZIGHOUSE_VERSION}/zighouse-linux-x86_64" -curl -L --fail -o zighouse "$url" +url="https://github.com/donge/zighouse/releases/download/${ZIGHOUSE_VERSION}/zighouse-linux-x86_64.gz" +curl -L --fail -o zighouse.gz "$url" +gunzip -f zighouse.gz printf '%s zighouse\n' "$ZIGHOUSE_SHA256" | sha256sum -c - chmod +x zighouse 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" ] } From 47ca6033aebab63a8a0236cf322be7c49490aa32 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Mon, 20 Jul 2026 23:38:28 +0000 Subject: [PATCH 3/4] zighouse: drive the generic binary via its ClickHouse-compatible HTTP server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The generic `v1.0.2` binary has no ClickBench-specific commands, and its `import` subcommand cannot write a store separate from the source Parquet file, so the previous embedded `import-clickbench-parquet-hot` / `query-timed` harness no longer works. Rework the entry as a server: - `start`/`stop`/`check` manage `zighouse serve` (native TCP on `--port`, HTTP on `--port`+1) and health-check via `/ping`. - `create.sql` is the canonical ClickBench `hits` schema in ClickHouse-native types the DDL parser understands. - `load` streams `hits.json` in <=256 MiB, line-aligned chunks, one `INSERT INTO hits FORMAT JSONEachRow` per chunk (the only bulk format the HTTP server ingests — it reads neither Parquet nor TSV), then runs `generic-smoke.sh`, which is now called from `load` per review feedback and rewritten to exercise the engine over HTTP. - `query` posts one statement over HTTP and reports the wall-clock time; `data-size` measures the store directory. The obsolete build-from-source `run.sh` is removed. Co-Authored-By: Claude Fable 5 --- zighouse/benchmark.sh | 5 +- zighouse/check | 5 +- zighouse/create.sql | 112 +++++++++++++++++++++++++++++++++++++- zighouse/data-size | 6 +- zighouse/generic-smoke.sh | 49 +++++++---------- zighouse/load | 47 +++++++++++++++- zighouse/query | 22 +++++++- zighouse/run.sh | 17 ------ zighouse/start | 20 ++++++- zighouse/stop | 9 +++ 10 files changed, 236 insertions(+), 56 deletions(-) delete mode 100755 zighouse/run.sh diff --git a/zighouse/benchmark.sh b/zighouse/benchmark.sh index c722454d56..6e193824d4 100755 --- a/zighouse/benchmark.sh +++ b/zighouse/benchmark.sh @@ -1,6 +1,9 @@ #!/bin/bash set -e -export BENCH_DOWNLOAD_SCRIPT="download-hits-parquet-single" +# The dataset is fetched inside ./load: JSONEachRow is the only bulk format the +# generic ZigHouse HTTP server can ingest, and there is no shared JSON download +# helper, so there is no separate download step here. +export BENCH_DOWNLOAD_SCRIPT="" export BENCH_DURABLE=yes exec ../lib/benchmark-common.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 index 1a10c2f27f..acc69ff9ce 100755 --- a/zighouse/generic-smoke.sh +++ b/zighouse/generic-smoke.sh @@ -1,36 +1,29 @@ #!/bin/bash -# Run arbitrary (non-ClickBench) SQL through ZigHouse's generic execution path. -# -# ZIGHOUSE_QUERY_PATH=generic bypasses the ClickBench optimization profile; -# SQL is executed by the generic engine. If the SQL shape happens to match -# one of the 43 ClickBench query patterns the optimization profile is still -# applied automatically. -# -# Run from this directory after benchmark.sh has imported the dataset: -# -# ./generic-smoke.sh -# +# Smoke-test ZigHouse's SQL engine on a handful of non-ClickBench statements +# through the ClickHouse-compatible HTTP interface. This runs automatically at +# the end of ./load (so the capability frontier is exercised on every run) and +# can also be invoked standalone from this directory once the server is up and +# the dataset has been loaded. set -u -STORE=${STORE:-/var/lib/zighouse/hits} -ZH=${ZIGHOUSE:-./zighouse} +: "${ZIGHOUSE_PORT:=28123}" +http_port=$((ZIGHOUSE_PORT + 1)) +base="http://127.0.0.1:${http_port}" run() { - echo "== $1 [$2] ==" - echo "SQL: $3" - ZIGHOUSE_QUERY_PATH=generic "$ZH" query "$STORE" "$3" || echo " -> error" - echo + echo "== $1 ==" + echo "SQL: $2" + curl -sS -G "${base}/" \ + --data-urlencode "query=$2" \ + --data-urlencode "default_format=TabSeparated" \ + || echo " -> error" + echo } -# Supported: scalar aggregates, COUNT(DISTINCT), GROUP BY on low-cardinality -# columns, WHERE with numeric and date conditions combined by AND. -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" likely "SELECT COUNT(*) FROM hits WHERE Age > 25 AND EventDate >= '2013-07-10'" -run "groupby_topk" likely "SELECT CounterID, COUNT(*) AS c FROM hits GROUP BY CounterID ORDER BY c DESC LIMIT 10" +run "count_all" "SELECT COUNT(*) FROM hits" +run "sum_with_filter" "SELECT SUM(AdvEngineID) FROM hits WHERE EventDate >= '2013-07-15'" +run "min_max_date" "SELECT MIN(EventDate), MAX(EventDate) FROM hits" +run "count_distinct" "SELECT COUNT(DISTINCT SearchEngineID) FROM hits" +run "groupby_topk" "SELECT RegionID, COUNT(*) AS c FROM hits GROUP BY RegionID ORDER BY c DESC LIMIT 5" -# Roadmap: GROUP BY on high-cardinality string columns, arbitrary table import. -run "groupby_url_topk" roadmap "SELECT URL, COUNT(*) FROM hits GROUP BY URL ORDER BY COUNT(*) DESC LIMIT 10" +exit 0 diff --git a/zighouse/load b/zighouse/load index b5ce530efb..fee96b66f2 100755 --- a/zighouse/load +++ b/zighouse/load @@ -1,6 +1,47 @@ #!/bin/bash -set -e +set -euo pipefail + +# ZigHouse's generic HTTP server ingests JSONEachRow (it cannot read Parquet or +# TSV directly). We stream the ClickBench hits.json dataset to it in chunks: +# the server buffers each request body whole and rejects anything over 256 MiB, +# and `split -C` keeps every JSON line intact within a chunk. +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) +: "${ZIGHOUSE_PORT:=28123}" +: "${ZIGHOUSE_LOAD_CHUNK:=200M}" +http_port=$((ZIGHOUSE_PORT + 1)) +base="http://127.0.0.1:${http_port}" + +# --- Fetch the dataset (JSONEachRow). Prefer the playground's pre-staged +# read-only copy; otherwise download and decompress. -------------------- +if [ ! -e hits.json ]; then + if [ -f /opt/clickbench/datasets_ro/hits.json ]; then + ln -sf /opt/clickbench/datasets_ro/hits.json hits.json + elif [ -f /opt/clickbench/datasets_ro/hits.json.gz ]; then + sudo apt-get install -y pigz + pigz -d -k -c /opt/clickbench/datasets_ro/hits.json.gz > hits.json + else + sudo apt-get install -y pigz + wget --continue --progress=dot:giga \ + 'https://datasets.clickhouse.com/hits_compatible/hits.json.gz' + pigz -d -f hits.json.gz + fi +fi + +# --- Schema -------------------------------------------------------------- +curl -sS --fail-with-body -G "${base}/" \ + --data-urlencode "query=$(cat "${SCRIPT_DIR}/create.sql")" >/dev/null + +# --- Bulk load: stream hits.json to the server in <=chunk-sized, line-aligned +# pieces, each posted as `INSERT INTO hits FORMAT JSONEachRow`. ---------- +export ZIGHOUSE_INSERT_URL="${base}/?query=INSERT%20INTO%20hits%20FORMAT%20JSONEachRow" +split -C "${ZIGHOUSE_LOAD_CHUNK}" \ + --filter='curl -sS --fail-with-body --data-binary @- "$ZIGHOUSE_INSERT_URL" >/dev/null' \ + hits.json -rm -rf zighouse-store -ZIGHOUSE_CLICKBENCH_SUBMIT=1 ZIGHOUSE_IMPORT_TRACE=1 ./zighouse import-clickbench-parquet-hot hits.parquet zighouse-store sync + +# hits.json (a symlink or a downloaded copy) is only needed for the load. +rm -f hits.json hits.json.gz + +# --- Post-load smoke test of the generic SQL engine (see generic-smoke.sh). +"${SCRIPT_DIR}/generic-smoke.sh" diff --git a/zighouse/query b/zighouse/query index 470f65e3d2..203755ef97 100755 --- a/zighouse/query +++ b/zighouse/query @@ -1,5 +1,23 @@ #!/bin/bash -set -e +# Reads a SQL query from stdin and runs it against the ZigHouse HTTP server. +# Stdout: query result (TabSeparated). +# Stderr: query runtime in fractional seconds on the last line. +# Exit non-zero on error. +set -euo pipefail + +: "${ZIGHOUSE_PORT:=28123}" +http_port=$((ZIGHOUSE_PORT + 1)) query=$(cat) -ZIGHOUSE_CLICKBENCH_SUBMIT=1 ./zighouse --backend native query-timed zighouse-store "$query" + +# -G moves the url-encoded params into the ?query= URL parameter; the server +# returns the result body, and curl's %{time_total} (whole-request wall time +# in seconds) is appended on its own trailing line. +out=$(curl -sS --fail-with-body -G "http://127.0.0.1:${http_port}/" \ + --data-urlencode "query=${query}" \ + --data-urlencode "default_format=TabSeparated" \ + -w $'\n%{time_total}') + +# Everything but the last line is the result; the last line is the timing. +printf '%s' "$out" | sed '$d' +printf '%s\n' "$out" | tail -n1 >&2 diff --git a/zighouse/run.sh b/zighouse/run.sh deleted file mode 100755 index c59729593d..0000000000 --- a/zighouse/run.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -set -euo pipefail - -SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) -CLICKBENCH_DIR=$(cd -- "${SCRIPT_DIR}/.." && pwd) - -: "${ZIGHOUSE_REPO:?Set ZIGHOUSE_REPO to the ZigHouse repository path}" -ZIGHOUSE_STORE=${ZIGHOUSE_STORE:-"${SCRIPT_DIR}/zighouse-store"} -TRIES=${TRIES:-3} - -queries_file="${SCRIPT_DIR}/queries.sql" -if [ ! -f "${queries_file}" ]; then - queries_file="${CLICKBENCH_DIR}/duckdb/queries.sql" -fi - -ZIGHOUSE_CLICKBENCH_SUBMIT=1 "${ZIGHOUSE_REPO}/zig-out/bin/zighouse" --backend native bench "${ZIGHOUSE_STORE}" "${queries_file}" \ - | grep '^\[' 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 From b9185ac2b1254413540dbf2d4ada9656f9dd1463 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Mon, 20 Jul 2026 23:38:29 +0000 Subject: [PATCH 4/4] zighouse: drop stale v0.2.0-clickbench result files These results were produced by the ClickBench-specific `v0.2.0-clickbench` binary that this PR no longer uses. They do not reflect the generic `v1.0.2` serve-mode entry and must be regenerated by a fresh benchmark run. Co-Authored-By: Claude Fable 5 --- zighouse/results/20260511/apple-m4-16gb.json | 57 ----- zighouse/results/20260511/c6i.4xlarge.json | 57 ----- zighouse/results/20260514/c6i.4xlarge.json | 235 ------------------- 3 files changed, 349 deletions(-) delete mode 100644 zighouse/results/20260511/apple-m4-16gb.json delete mode 100644 zighouse/results/20260511/c6i.4xlarge.json delete mode 100644 zighouse/results/20260514/c6i.4xlarge.json diff --git a/zighouse/results/20260511/apple-m4-16gb.json b/zighouse/results/20260511/apple-m4-16gb.json deleted file mode 100644 index 59b215bf3d..0000000000 --- a/zighouse/results/20260511/apple-m4-16gb.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "system": "ZigHouse", - "date": "2026-05-11", - "machine": "apple-m4-16gb", - "cluster_size": 1, - "proprietary": "no", - "hardware": "cpu", - "tuned": "yes", - "tags": ["Zig", "column-oriented", "embedded", "parquet", "tuned"], - "load_time": 95.825303, - "data_size": 11041472512, - "result": [ - [0.000020, 0.000011, 0.000010], - [0.288477, 0.003584, 0.003517], - [0.286699, 0.006285, 0.006197], - [1.148201, 0.012570, 0.012646], - [0.678655, 0.133984, 0.133487], - [0.674130, 0.057838, 0.057984], - [0.581857, 0.006325, 0.006117], - [0.027784, 0.027646, 0.027591], - [0.936706, 0.342146, 0.341331], - [0.326893, 0.336997, 0.330520], - [0.249497, 0.082829, 0.092776], - [0.402567, 0.109866, 0.098120], - [0.238186, 0.194607, 0.197506], - [0.385967, 0.384434, 0.357218], - [0.778353, 0.481491, 0.509972], - [0.466834, 0.234330, 0.226432], - [0.593496, 0.393404, 0.386392], - [0.000203, 0.000006, 0.000001], - [1.554993, 1.106129, 1.125513], - [0.768414, 0.012143, 0.012535], - [0.194666, 0.029126, 0.029298], - [0.005878, 0.000168, 0.000118], - [0.005593, 0.002175, 0.002152], - [0.685523, 0.332071, 0.331913], - [1.311678, 0.188993, 0.188652], - [1.064152, 0.332794, 0.335596], - [0.191390, 0.190310, 0.190312], - [2.793248, 0.946305, 0.967854], - [0.000492, 0.000060, 0.000040], - [0.329938, 0.003540, 0.003151], - [1.540300, 0.239452, 0.208305], - [0.000215, 0.000003, 0.000001], - [3.701904, 2.250702, 2.242093], - [15.542399, 0.000010, 0.000001], - [0.000005, 0.000001, 0.000001], - [0.478586, 0.321139, 0.278451], - [12.118079, 0.041698, 0.038983], - [0.009425, 0.006738, 0.006697], - [9.957975, 0.049342, 0.026761], - [20.600735, 0.190457, 0.168816], - [0.031845, 0.031687, 0.031764], - [0.049392, 0.029151, 0.028690], - [0.035122, 0.026112, 0.026040] - ] -} diff --git a/zighouse/results/20260511/c6i.4xlarge.json b/zighouse/results/20260511/c6i.4xlarge.json deleted file mode 100644 index a227f18445..0000000000 --- a/zighouse/results/20260511/c6i.4xlarge.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "system": "ZigHouse", - "date": "2026-05-11", - "machine": "c6i.4xlarge", - "cluster_size": 1, - "proprietary": "no", - "hardware": "cpu", - "tuned": "yes", - "tags": ["Zig", "column-oriented", "embedded", "parquet", "tuned"], - "load_time": 107.325948, - "data_size": 10907660072, - "result": [ - [0.000011, 0.000003, 0.000003], - [0.024972, 0.021235, 0.021001], - [0.050208, 0.046460, 0.046737], - [0.096349, 0.081752, 0.081741], - [0.285518, 0.280157, 0.277794], - [0.161092, 0.154534, 0.154430], - [0.054587, 0.047533, 0.047683], - [0.040411, 0.040428, 0.040350], - [0.667198, 0.664248, 0.665061], - [0.469939, 0.469675, 0.465138], - [0.628110, 0.629003, 0.628740], - [1.224084, 1.225191, 1.226756], - [0.250038, 0.237991, 0.236879], - [0.573394, 0.569330, 0.569404], - [1.354701, 1.353070, 1.352093], - [0.315275, 0.314364, 0.315598], - [0.762463, 0.758809, 0.759704], - [0.000013, 0.000003, 0.000003], - [1.711261, 1.714679, 1.712196], - [0.082314, 0.082138, 0.082798], - [0.022687, 0.022595, 0.022685], - [0.000231, 0.000154, 0.000134], - [0.002759, 0.002641, 0.002569], - [0.494700, 0.492390, 0.492110], - [0.332414, 0.332675, 0.334685], - [0.489888, 0.486122, 0.486588], - [0.343629, 0.343852, 0.344576], - [0.202833, 0.188492, 0.188672], - [0.000123, 0.000044, 0.000036], - [0.023822, 0.023242, 0.023103], - [0.598550, 0.581554, 0.585012], - [0.000036, 0.000003, 0.000002], - [7.308801, 7.276433, 7.201636], - [14.773791, 0.000008, 0.000002], - [0.000002, 0.000001, 0.000001], - [0.429645, 0.431648, 0.429949], - [8.305794, 0.102916, 0.102900], - [0.007857, 0.007851, 0.007893], - [8.603302, 0.072670, 0.071581], - [15.922052, 0.314574, 0.303756], - [0.085281, 0.085315, 0.085155], - [0.117885, 0.117910, 0.118037], - [0.062024, 0.061896, 0.062019] - ] -} diff --git a/zighouse/results/20260514/c6i.4xlarge.json b/zighouse/results/20260514/c6i.4xlarge.json deleted file mode 100644 index 482a7e8da9..0000000000 --- a/zighouse/results/20260514/c6i.4xlarge.json +++ /dev/null @@ -1,235 +0,0 @@ -{ - "system": "ZigHouse", - "date": "2026-05-14", - "machine": "c6i.4xlarge", - "cluster_size": 1, - "proprietary": "no", - "hardware": "cpu", - "tuned": "yes", - "tags": [ - "Zig", - "column-oriented", - "embedded", - "parquet", - "tuned" - ], - "load_time": 116.239, - "data_size": 10907676486, - "result": [ - [ - 1.8e-05, - 3e-06, - 4e-06 - ], - [ - 0.025528, - 0.017548, - 0.01746 - ], - [ - 0.045097, - 0.037667, - 0.037637 - ], - [ - 0.093562, - 0.065274, - 0.065342 - ], - [ - 0.2765, - 0.259201, - 0.258945 - ], - [ - 0.160691, - 0.148757, - 0.148206 - ], - [ - 0.051539, - 0.03794, - 0.037933 - ], - [ - 0.038356, - 0.038266, - 0.038308 - ], - [ - 0.611857, - 0.608666, - 0.60935 - ], - [ - 0.450949, - 0.449545, - 0.443805 - ], - [ - 0.603384, - 0.600638, - 0.601455 - ], - [ - 1.181358, - 1.181901, - 1.181283 - ], - [ - 0.242423, - 0.231455, - 0.229903 - ], - [ - 0.547958, - 0.555233, - 0.555539 - ], - [ - 1.082624, - 1.079799, - 1.074035 - ], - [ - 0.283271, - 0.27663, - 0.276807 - ], - [ - 0.720087, - 0.711285, - 0.710939 - ], - [ - 1.8e-05, - 2e-06, - 2e-06 - ], - [ - 1.61783, - 1.616456, - 1.614723 - ], - [ - 0.066287, - 0.065907, - 0.066012 - ], - [ - 0.024226, - 0.024, - 0.023862 - ], - [ - 0.000227, - 0.000149, - 0.000128 - ], - [ - 0.002746, - 0.002492, - 0.002419 - ], - [ - 0.473285, - 0.471103, - 0.47166 - ], - [ - 0.334994, - 0.33642, - 0.337482 - ], - [ - 0.535499, - 0.522643, - 0.523208 - ], - [ - 0.351209, - 0.349393, - 0.35061 - ], - [ - 0.247331, - 0.221126, - 0.22125 - ], - [ - 9.5e-05, - 4.1e-05, - 3.5e-05 - ], - [ - 0.019097, - 0.019179, - 0.01907 - ], - [ - 0.564347, - 0.562521, - 0.562546 - ], - [ - 2.6e-05, - 3e-06, - 2e-06 - ], - [ - 6.196822, - 6.180835, - 6.194565 - ], - [ - 14.165038, - 5e-06, - 1e-06 - ], - [ - 2e-06, - 1e-06, - 1e-06 - ], - [ - 0.398704, - 0.398933, - 0.398398 - ], - [ - 8.284818, - 0.075016, - 0.074296 - ], - [ - 0.008249, - 0.007887, - 0.007798 - ], - [ - 8.438275, - 0.050873, - 0.050586 - ], - [ - 15.948981, - 0.388244, - 0.38619 - ], - [ - 0.081452, - 0.081091, - 0.081063 - ], - [ - 0.113807, - 0.113659, - 0.113587 - ], - [ - 0.057215, - 0.057094, - 0.057103 - ] - ] -} \ No newline at end of file