diff --git a/opteryx-skene/install b/opteryx-skene/install index 21ba004257..10ce317c7e 100755 --- a/opteryx-skene/install +++ b/opteryx-skene/install @@ -29,16 +29,18 @@ if [ ! -d "$HOME/opteryx_venv" ]; then fi "$HOME/opteryx_venv/bin/python" -m pip install --upgrade pip -# Pulls the cp314 wheel for the latest release. -"$HOME/opteryx_venv/bin/python" -m pip install --upgrade opteryx-core +# Pinned so a published result is reproducible against a named release. +OPTERYX_VERSION=0.9.155 +"$HOME/opteryx_venv/bin/python" -m pip install "opteryx-core==${OPTERYX_VERSION}" # Fail loudly here rather than 43 queries later if pip silently fell back to a # source build or resolved an interpreter we did not expect. -"$HOME/opteryx_venv/bin/python" - <<'PY' +"$HOME/opteryx_venv/bin/python" - "$OPTERYX_VERSION" <<'PY' import sys import opteryx print(f"python {sys.version.split()[0]} (GIL enabled: {sys._is_gil_enabled()})") print(f"opteryx-core {opteryx.__version__}") +assert opteryx.__version__ == sys.argv[1], f"expected opteryx-core {sys.argv[1]}, got {opteryx.__version__}" PY diff --git a/opteryx-skene/results/20261004/c6a.2xlarge.json b/opteryx-skene/results/20261004/c6a.2xlarge.json new file mode 100644 index 0000000000..b2b54b75b2 --- /dev/null +++ b/opteryx-skene/results/20261004/c6a.2xlarge.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx", + "date": "2026-10-04", + "machine": "c6a.2xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 244, + "data_size": 11703080392, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.563, 0.085, 0.085], + [1.05, 0.253, 0.264], + [0.757, 0.087, 0.089], + [0.74, 0.088, 0.088], + [2.126, 1.134, 1.169], + [1.708, 0.697, 0.706], + [0.75, 0.085, 0.086], + [1.037, 0.263, 0.263], + [2.317, 1.307, 1.267], + [2.78, 1.585, 1.598], + [1.347, 0.343, 0.344], + [1.438, 0.403, 0.407], + [2.034, 1.003, 0.997], + [2.641, 1.397, 1.41], + [2.231, 1.136, 1.115], + [2.12, 1.174, 1.194], + [3.47, 2.222, 2.218], + [0.872, 0.126, 0.126], + [6.045, 4.329, 4.273], + [1.072, 0.188, 0.199], + [7.017, 1.821, 1.846], + [8.039, 2.108, 2.037], + [13.402, 3.07, 3.115], + [10.405, 1.886, 1.868], + [2.357, 0.683, 0.685], + [1.336, 0.543, 0.545], + [2.549, 0.702, 0.69], + [6.908, 1.13, 1.13], + [7.084, 4.859, 4.948], + [0.79, 0.124, 0.123], + [2.378, 1.017, 1.032], + [5.159, 1.283, 1.212], + [6.185, 4.843, 4.829], + [7.328, 4.163, 4.086], + [7.204, 4.101, 4.162], + [1.8, 1.137, 1.144], + [0.937, 0.213, 0.214], + [0.834, 0.126, 0.13], + [0.901, 0.184, 0.182], + [1.139, 0.38, 0.363], + [0.843, 0.122, 0.123], + [0.812, 0.116, 0.114], + [0.841, 0.122, 0.118] +] + } + \ No newline at end of file diff --git a/opteryx-skene/results/20261004/c6a.4xlarge.json b/opteryx-skene/results/20261004/c6a.4xlarge.json new file mode 100644 index 0000000000..ecd10f4fcf --- /dev/null +++ b/opteryx-skene/results/20261004/c6a.4xlarge.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx", + "date": "2026-10-04", + "machine": "c6a.4xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 172, + "data_size": 11698473632, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.774, 0.083, 0.083], + [0.958, 0.177, 0.177], + [0.802, 0.085, 0.083], + [0.806, 0.084, 0.084], + [1.685, 0.711, 0.701], + [1.527, 0.477, 0.48], + [0.791, 0.085, 0.085], + [0.953, 0.179, 0.178], + [2.021, 0.946, 0.956], + [2.301, 1.111, 1.139], + [1.292, 0.27, 0.269], + [1.368, 0.309, 0.305], + [1.762, 0.706, 0.704], + [2.248, 0.971, 0.983], + [1.877, 0.783, 0.782], + [1.783, 0.806, 0.792], + [2.762, 1.503, 1.504], + [0.874, 0.117, 0.119], + [4.431, 2.81, 2.825], + [1.098, 0.162, 0.162], + [7.168, 1.553, 1.559], + [8.189, 1.758, 1.74], + [13.591, 2.686, 2.665], + [10.379, 1.627, 1.662], + [2.428, 0.528, 0.529], + [1.137, 0.403, 0.401], + [2.623, 0.542, 0.54], + [6.864, 1.005, 1.013], + [6.966, 3.45, 3.461], + [0.69, 0.124, 0.122], + [1.854, 0.743, 0.742], + [5.198, 1.034, 0.999], + [5.543, 3.718, 3.752], + [7.297, 2.967, 2.928], + [7.324, 2.965, 2.964], + [1.444, 0.746, 0.758], + [0.84, 0.211, 0.202], + [0.897, 0.117, 0.114], + [0.97, 0.162, 0.169], + [1.144, 0.344, 0.345], + [0.874, 0.115, 0.112], + [0.901, 0.109, 0.109], + [0.903, 0.116, 0.114] +] + } + \ No newline at end of file diff --git a/opteryx-skene/results/20261004/c6a.large.json b/opteryx-skene/results/20261004/c6a.large.json new file mode 100644 index 0000000000..7ac2c6385c --- /dev/null +++ b/opteryx-skene/results/20261004/c6a.large.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx", + "date": "2026-10-04", + "machine": "c6a.large", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 867, + "data_size": 11689868024, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.727, 0.086, 0.09], + [1.559, 0.818, 0.833], + [0.72, 0.088, 0.087], + [0.722, 0.086, 0.086], + [4.333, 3.441, 3.33], + [3.19, 2.022, 2.017], + [0.724, 0.088, 0.087], + [1.547, 0.815, 0.826], + [4.491, 3.439, 3.362], + [5.79, 4.536, 4.516], + [1.939, 0.878, 0.878], + [2.189, 1.091, 1.091], + [3.976, 2.814, 2.779], + [5.606, 4.092, 4.066], + [4.43, 3.251, 3.214], + [4.52, 3.547, 3.481], + [8.13, 7.373, 7.266], + [0.914, 0.155, 0.157], + [94.995, 93.263, 96.266], + [1.27, 0.369, 0.375], + [8.264, 4.859, 4.871], + [9.561, 5.294, 5.609], + [14.226, 12.415, 11.897], + [10.908, 5.15, 5.269], + [3.675, 1.816, 1.823], + [2.654, 1.468, 1.431], + [3.68, 1.877, 1.866], + [6.959, 2.758, 2.827], + [16.823, 16.317, 16.425], + [0.767, 0.126, 0.128], + [4.59, 2.97, 2.94], + [5.901, 3.096, 3.066], + [232.075, 233.01, 232.763], + [49.688, 50.008, 49.902], + [50.661, 49.162, 50.792], + [4.349, 3.457, 3.434], + [1.073, 0.359, 0.355], + [0.878, 0.182, 0.184], + [0.968, 0.244, 0.241], + [1.427, 0.678, 0.656], + [0.862, 0.156, 0.156], + [0.856, 0.151, 0.152], + [0.856, 0.159, 0.158] +] + } + \ No newline at end of file diff --git a/opteryx-skene/results/20261004/c6a.metal.json b/opteryx-skene/results/20261004/c6a.metal.json new file mode 100644 index 0000000000..bdd5edf4e0 --- /dev/null +++ b/opteryx-skene/results/20261004/c6a.metal.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx", + "date": "2026-10-04", + "machine": "c6a.metal", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 79, + "data_size": 11705606444, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.706, 0.092, 0.092], + [0.868, 0.156, 0.166], + [0.719, 0.092, 0.092], + [0.717, 0.095, 0.095], + [1.271, 0.369, 0.377], + [1.319, 0.336, 0.318], + [0.716, 0.094, 0.091], + [0.883, 0.16, 0.157], + [1.644, 0.656, 0.729], + [1.84, 0.785, 0.745], + [1.211, 0.315, 0.304], + [0.905, 0.366, 0.374], + [1.024, 0.485, 0.487], + [2.055, 0.594, 0.581], + [1.038, 0.456, 0.536], + [1.341, 0.567, 0.558], + [2.202, 0.945, 0.993], + [0.539, 0.132, 0.126], + [4.119, 1.663, 1.727], + [0.633, 0.189, 0.186], + [6.956, 1.281, 1.241], + [8.197, 1.331, 1.39], + [13.762, 1.687, 1.758], + [10.355, 1.041, 1.042], + [2.246, 0.42, 0.433], + [0.851, 0.321, 0.344], + [2.241, 0.422, 0.475], + [6.719, 0.796, 0.818], + [6.795, 1.698, 1.688], + [0.489, 0.129, 0.127], + [1.834, 0.576, 0.577], + [4.723, 0.797, 0.825], + [4.765, 2.529, 2.65], + [7.359, 1.957, 1.881], + [7.342, 1.923, 1.912], + [1.022, 0.528, 0.535], + [0.941, 0.213, 0.22], + [0.804, 0.148, 0.136], + [0.896, 0.181, 0.183], + [1.116, 0.323, 0.34], + [0.816, 0.126, 0.125], + [0.805, 0.133, 0.121], + [0.803, 0.129, 0.125] +] + } + \ No newline at end of file diff --git a/opteryx-skene/results/20261004/c6a.xlarge.json b/opteryx-skene/results/20261004/c6a.xlarge.json new file mode 100644 index 0000000000..c5d12e5811 --- /dev/null +++ b/opteryx-skene/results/20261004/c6a.xlarge.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx", + "date": "2026-10-04", + "machine": "c6a.xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 642, + "data_size": 11703343804, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.746, 0.084, 0.087], + [1.198, 0.411, 0.448], + [0.736, 0.088, 0.086], + [0.738, 0.082, 0.082], + [2.954, 1.951, 1.944], + [2.356, 1.224, 1.204], + [0.724, 0.085, 0.085], + [1.19, 0.434, 0.449], + [3.2, 2.041, 2.016], + [3.887, 2.639, 2.629], + [1.599, 0.514, 0.527], + [1.769, 0.649, 0.629], + [2.764, 1.634, 1.616], + [3.882, 2.538, 2.398], + [3.126, 1.91, 1.878], + [2.952, 1.967, 2.074], + [5.387, 3.914, 3.817], + [0.898, 0.142, 0.142], + [9.804, 8.46, 8.078], + [1.207, 0.247, 0.247], + [7.028, 2.771, 2.813], + [8.177, 3.162, 3.242], + [13.61, 4.991, 4.868], + [10.796, 3.043, 3.036], + [2.697, 1.063, 1.107], + [1.911, 0.874, 0.914], + [2.716, 1.141, 1.148], + [6.999, 1.655, 1.651], + [11.015, 8.465, 8.53], + [0.779, 0.126, 0.128], + [3.318, 1.728, 1.725], + [5.242, 1.897, 1.909], + [28.704, 25.784, 25.63], + [9.806, 9.499, 9.567], + [9.987, 9.285, 9.349], + [2.825, 1.879, 1.915], + [0.999, 0.279, 0.264], + [0.841, 0.14, 0.142], + [0.91, 0.197, 0.193], + [1.293, 0.565, 0.571], + [0.858, 0.141, 0.137], + [0.839, 0.125, 0.124], + [0.832, 0.142, 0.142] +] + } + \ No newline at end of file diff --git a/opteryx-skene/results/20261004/c7a.metal-48xl.json b/opteryx-skene/results/20261004/c7a.metal-48xl.json new file mode 100644 index 0000000000..b034aa04e9 --- /dev/null +++ b/opteryx-skene/results/20261004/c7a.metal-48xl.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx", + "date": "2026-10-04", + "machine": "c7a.metal-48xl", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 74, + "data_size": 11705606444, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.707, 0.085, 0.081], + [0.854, 0.138, 0.129], + [0.716, 0.084, 0.082], + [0.711, 0.084, 0.08], + [1.261, 0.343, 0.343], + [1.301, 0.285, 0.285], + [0.465, 0.085, 0.081], + [0.664, 0.15, 0.142], + [1.587, 0.597, 0.578], + [1.714, 0.673, 0.694], + [0.867, 0.293, 0.288], + [0.921, 0.343, 0.337], + [1.003, 0.399, 0.413], + [1.621, 0.486, 0.491], + [1.05, 0.408, 0.405], + [1.038, 0.536, 0.525], + [2.136, 0.807, 0.805], + [0.56, 0.115, 0.112], + [3.972, 1.408, 1.361], + [0.673, 0.164, 0.159], + [6.874, 1.1, 1.07], + [8.139, 1.173, 1.194], + [13.674, 1.585, 1.502], + [10.339, 0.994, 0.943], + [2.274, 0.385, 0.377], + [0.909, 0.272, 0.263], + [2.28, 0.375, 0.389], + [6.75, 0.704, 0.727], + [6.698, 1.418, 1.511], + [0.507, 0.114, 0.109], + [1.762, 0.509, 0.52], + [4.667, 0.736, 0.699], + [4.55, 2.329, 2.152], + [7.273, 1.712, 1.764], + [7.237, 1.716, 1.729], + [1.019, 0.49, 0.487], + [0.929, 0.199, 0.193], + [0.804, 0.12, 0.116], + [0.888, 0.17, 0.163], + [1.08, 0.31, 0.305], + [0.812, 0.117, 0.113], + [0.802, 0.114, 0.114], + [0.804, 0.12, 0.117] +] + } + \ No newline at end of file diff --git a/opteryx-skene/results/20261004/c8g.4xlarge.json b/opteryx-skene/results/20261004/c8g.4xlarge.json new file mode 100644 index 0000000000..6a8e3b0a3f --- /dev/null +++ b/opteryx-skene/results/20261004/c8g.4xlarge.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx", + "date": "2026-10-04", + "machine": "c8g.4xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 144, + "data_size": 11698473632, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.618, 0.062, 0.062], + [0.742, 0.108, 0.107], + [0.621, 0.061, 0.061], + [0.617, 0.061, 0.061], + [1.173, 0.361, 0.347], + [1.264, 0.252, 0.257], + [0.533, 0.062, 0.062], + [0.626, 0.109, 0.108], + [1.233, 0.507, 0.506], + [1.564, 0.583, 0.586], + [1.022, 0.158, 0.161], + [1.065, 0.181, 0.182], + [1.238, 0.342, 0.331], + [1.783, 0.45, 0.451], + [1.242, 0.385, 0.388], + [1.194, 0.374, 0.376], + [1.794, 0.664, 0.667], + [0.695, 0.08, 0.083], + [3.493, 1.186, 1.179], + [0.85, 0.108, 0.107], + [6.841, 0.702, 0.701], + [8.047, 0.75, 0.751], + [13.426, 1.078, 1.106], + [10.389, 0.646, 0.638], + [2.358, 0.264, 0.264], + [0.965, 0.202, 0.198], + [2.363, 0.269, 0.27], + [6.768, 0.438, 0.43], + [6.525, 1.463, 1.459], + [0.569, 0.09, 0.09], + [1.708, 0.341, 0.338], + [4.702, 0.422, 0.417], + [3.954, 1.23, 1.238], + [6.964, 1.246, 1.237], + [6.965, 1.233, 1.225], + [1.018, 0.358, 0.353], + [0.67, 0.143, 0.143], + [0.583, 0.085, 0.085], + [0.637, 0.111, 0.111], + [0.778, 0.228, 0.224], + [0.683, 0.083, 0.082], + [0.678, 0.081, 0.08], + [0.679, 0.086, 0.086] +] + } + \ No newline at end of file diff --git a/opteryx-skene/results/20261004/c8g.metal-48xl.json b/opteryx-skene/results/20261004/c8g.metal-48xl.json new file mode 100644 index 0000000000..895eb44c64 --- /dev/null +++ b/opteryx-skene/results/20261004/c8g.metal-48xl.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx", + "date": "2026-10-04", + "machine": "c8g.metal-48xl", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 79, + "data_size": 11705606444, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.62, 0.068, 0.067], + [0.751, 0.109, 0.106], + [0.633, 0.068, 0.067], + [0.628, 0.068, 0.068], + [1.116, 0.236, 0.25], + [1.049, 0.217, 0.212], + [0.504, 0.068, 0.068], + [0.657, 0.115, 0.113], + [1.224, 0.434, 0.437], + [1.355, 0.483, 0.482], + [0.932, 0.194, 0.191], + [0.989, 0.222, 0.226], + [1.079, 0.275, 0.275], + [1.646, 0.359, 0.367], + [1.18, 0.286, 0.292], + [0.983, 0.306, 0.316], + [1.692, 0.532, 0.521], + [0.59, 0.09, 0.09], + [3.4, 0.899, 0.901], + [0.722, 0.122, 0.123], + [6.848, 0.883, 0.883], + [8.062, 0.943, 0.917], + [13.438, 1.199, 1.216], + [10.252, 0.794, 0.767], + [2.296, 0.283, 0.298], + [1.042, 0.207, 0.206], + [2.295, 0.303, 0.293], + [6.763, 0.5, 0.501], + [6.387, 1.003, 1.021], + [0.545, 0.097, 0.096], + [1.668, 0.34, 0.335], + [4.641, 0.506, 0.507], + [4.17, 1.588, 1.808], + [7.048, 1.236, 1.201], + [7.041, 1.209, 1.197], + [0.973, 0.33, 0.312], + [0.663, 0.155, 0.149], + [0.553, 0.097, 0.097], + [0.621, 0.123, 0.119], + [0.839, 0.232, 0.231], + [0.704, 0.09, 0.093], + [0.697, 0.088, 0.089], + [0.697, 0.096, 0.095] +] + } + \ No newline at end of file diff --git a/opteryx-skene/results/20261004/t3a.small.json b/opteryx-skene/results/20261004/t3a.small.json new file mode 100644 index 0000000000..033c0ebb1c --- /dev/null +++ b/opteryx-skene/results/20261004/t3a.small.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx", + "date": "2026-10-04", + "machine": "t3a.small", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 7534, + "data_size": 11689868024, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.91, 0.192, 0.19], + [2.173, 1.314, 1.332], + [0.844, 0.174, 0.18], + [0.876, 0.203, 0.197], + [7.143, 5.897, 5.844], + [5.075, 4.04, 3.954], + [0.918, 0.182, 0.181], + [2.15, 1.323, 1.331], + [7.903, 6.408, 6.453], + [9.41, 8.045, 8.003], + [2.812, 1.522, 1.508], + [3.011, 1.937, 1.873], + [6.229, 5.471, 5.363], + [16.301, 12.321, 12.659], + [7.782, 6.859, 6.566], + [7.698, 7.304, 6.94], + [50.759, 47.284, 47.963], + [1.089, 0.282, 0.287], + [183.661, 188.597, 190.973], + [1.627, 0.73, 0.723], + [11.1, 10.566, 10.787], + [13.027, 12.288, 12.494], + [20.134, 19.616, 20.241], + [13.652, 13.154, 13.35], + [4.797, 3.045, 3.067], + [3.639, 2.473, 2.414], + [4.98, 3.207, 3.058], + [8.28, 7.805, 7.75], + [71.921, 88.224, 82.53], + [0.905, 0.267, 0.254], + [7.047, 5.285, 5.444], + [8.465, 7.753, 7.781], + [335.058, 339.298, 335.222], + [82.646, 83.351, 156.733], + [479.587, 472.445, 479.428], + [10.856, 6.839, 6.726], + [1.315, 0.607, 0.605], + [1.014, 0.325, 0.321], + [1.121, 0.409, 0.416], + [1.925, 1.126, 1.096], + [0.984, 0.275, 0.292], + [0.957, 0.27, 0.312], + [0.954, 0.278, 0.282] +] + } + \ No newline at end of file diff --git a/opteryx/README.md b/opteryx/README.md index 2338ac4c10..b3f4fc5c75 100644 --- a/opteryx/README.md +++ b/opteryx/README.md @@ -13,6 +13,27 @@ For more information, visit: This page benchmarks Opteryx (PyPI package `opteryx-core`) using the split Parquet files provided by ClickBench. +### Process model + +Opteryx is an in-process engine, and this entry runs it the way it is deployed: +as a long-lived service. `start` launches `server.py`, a standard-library HTTP +wrapper that imports `opteryx` and waits; `query` posts each statement to it. +This is the same shape as the pandas/polars entries. + +- `BENCH_RESTARTABLE=yes`: the driver stops the server, drops the OS page cache + and starts a fresh process before every query, so try 1 is cold. Tries 2-3 + run in the same process. +- `BENCH_DURABLE=yes`: the data is Parquet on disk and nothing is loaded into + process memory. +- `start` launches the service and nothing else: no warm-up query, and the + dataset is not touched. `check` reads `/health` and runs no query. +- There is no query-result cache. What carries from try 1 to tries 2-3 is + process state: imported modules and the engine's Parquet footer and schema + caches. +- The reported time is the server-side drain of `execute_to_morsels`, the same + span the previous process-per-query entry measured. Rendering the result as + TSV happens after the clock stops. + --- ## Generating Benchmark Results @@ -60,6 +81,10 @@ Parquet files provided by ClickBench. no runtime dependencies, so `install` is a single binary-wheel download with no on-box compilation and no toolchain. +`install` pins the release (`opteryx-core==0.9.155`, the latest release when +this entry was drafted) and fails if the imported +version differs, so a published result names the build that produced it. + ### Query dialect `queries.sql` adapts queries to Opteryx's dialect. The adaptations are syntactic @@ -76,12 +101,9 @@ on-box compilation and no toolchain. ### Hardware coverage -Results are published for instance types with **32 or fewer vCPUs**. The account -used for these runs is limited to 32 concurrent on-demand vCPUs, so the 192-vCPU -machines in the ClickBench fleet (`c6a.metal`, `c7a.metal-48xl`, -`c8g.metal-48xl`) could not be launched. The published set spans 2 to 16 vCPUs -on both x86_64 (`c6a.*`, `t3a.small`) and AArch64 (`c8g.*`), which covers the -small/medium range of the standard fleet on both architectures. +The results submitted with this entry are from `c6a.4xlarge`, the canonical +machine. Results for the other instance types in the ClickBench fleet come from +the ClickBench benchmark runs, not from submitted measurements. ### Known Issues diff --git a/opteryx/benchmark.sh b/opteryx/benchmark.sh index b7ae16ae72..ad5d0266f0 100755 --- a/opteryx/benchmark.sh +++ b/opteryx/benchmark.sh @@ -1,9 +1,12 @@ #!/bin/bash export BENCH_DOWNLOAD_SCRIPT="download-hits-parquet-partitioned" -export BENCH_RESTARTABLE=no -# 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. +# Long-lived query server (server.py). Restartable: the driver stops it, drops +# caches and starts it again before every query, so try 1 is a cold process; +# tries 2-3 hit the same process. Durable: the data is Parquet on disk, nothing +# lives in process memory, so ./load is not re-run. +export BENCH_RESTARTABLE=yes +export BENCH_DURABLE=yes +# Concurrent-QPS test stays off for now: server.py serves one request at a +# time, so N connections would measure a queue, not throughput. export BENCH_CONCURRENT_DURATION="${BENCH_CONCURRENT_DURATION:-0}" exec ../lib/benchmark-common.sh diff --git a/opteryx/check b/opteryx/check index ed305e8015..ba13ba5d7f 100755 --- a/opteryx/check +++ b/opteryx/check @@ -1,34 +1,12 @@ #!/bin/bash -set -e - -# Smoke test that actually executes through the engine and propagates a -# non-zero exit on failure. The old `python -m opteryx "SELECT version()"` -# CLI path is unusable here for two reasons: -# -# 1. opteryx-core's single-run CLI calls the removed opteryx.query(), -# catches the AttributeError, and STILL exits 0 -- a false green that -# would let a broken install pass this check. -# 2. `version()` is not a function in the current engine; the version is -# exposed as the system variable `@@version`. -# -# This matters more than it looks: bench_load() in lib/benchmark-common.sh -# calls ./check unconditionally, AFTER the ~14 GB download and load. A check -# that cannot pass burns the whole setup cost before failing. +# Succeeds only while the server is up and serving a real opteryx-core install. +# Must FAIL when the server is down: with BENCH_RESTARTABLE=yes the driver waits +# for that before dropping caches for each cold try. # -# Assert the shape of the value rather than a literal, so the check does not -# need editing on every release. -"$HOME/opteryx_venv/bin/python" - <<'PY' -import re - -import opteryx - -session = opteryx.session() -morsels = list(session.execute_to_morsels("SELECT @@version")) -session.close() +# Runs no query — the driver calls this before every cold try, and executing +# anything here would warm the engine ahead of the measurement. The version +# shape is asserted instead of a literal so this needs no edit per release. +set -e -assert morsels, "SELECT @@version returned no morsels" -value = list(morsels[0][0])[0] -if isinstance(value, (bytes, bytearray)): - value = value.decode() -assert re.fullmatch(r"\d+\.\d+\.\d+.*", str(value)), f"unexpected version {value!r}" -PY +version=$(curl -sf http://127.0.0.1:8421/health) +[[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]] diff --git a/opteryx/install b/opteryx/install index 21ba004257..10ce317c7e 100755 --- a/opteryx/install +++ b/opteryx/install @@ -29,16 +29,18 @@ if [ ! -d "$HOME/opteryx_venv" ]; then fi "$HOME/opteryx_venv/bin/python" -m pip install --upgrade pip -# Pulls the cp314 wheel for the latest release. -"$HOME/opteryx_venv/bin/python" -m pip install --upgrade opteryx-core +# Pinned so a published result is reproducible against a named release. +OPTERYX_VERSION=0.9.155 +"$HOME/opteryx_venv/bin/python" -m pip install "opteryx-core==${OPTERYX_VERSION}" # Fail loudly here rather than 43 queries later if pip silently fell back to a # source build or resolved an interpreter we did not expect. -"$HOME/opteryx_venv/bin/python" - <<'PY' +"$HOME/opteryx_venv/bin/python" - "$OPTERYX_VERSION" <<'PY' import sys import opteryx print(f"python {sys.version.split()[0]} (GIL enabled: {sys._is_gil_enabled()})") print(f"opteryx-core {opteryx.__version__}") +assert opteryx.__version__ == sys.argv[1], f"expected opteryx-core {sys.argv[1]}, got {opteryx.__version__}" PY diff --git a/opteryx/query b/opteryx/query index f2ca00e871..9fde2b8ae5 100755 --- a/opteryx/query +++ b/opteryx/query @@ -1,42 +1,28 @@ #!/bin/bash -# Reads a SQL query from stdin, runs it via opteryx-core (Python in-process) -# against the partitioned parquet under ./hits/. +# Reads a SQL query from stdin and runs it on the long-lived server. # Stdout: query result as TSV (header + rows). -# Stderr: query runtime in fractional seconds on the last line. +# Stderr: query runtime in fractional seconds on the last line (server-measured +# drain of execute_to_morsels; see server.py). +# Exit non-zero on error; the traceback is in server.log. set -e -query=$(cat) +body=$(mktemp) +trap 'rm -f "$body"' EXIT -"$HOME/opteryx_venv/bin/python" - "$query" <<'PY' -import sys -import timeit +meta=$(curl -sS -o "$body" -w '%{http_code} %header{x-elapsed}' \ + -X POST --data-binary @- http://127.0.0.1:8421/query) || { + echo "query failed: no response from server (see server.log)" >&2 + exit 1 +} -import opteryx +code=${meta%% *} +elapsed=${meta#* } -query = sys.argv[1] +if [ "$code" != "200" ] || [ -z "$elapsed" ]; then + echo "query failed: HTTP $code" >&2 + cat "$body" >&2 + exit 1 +fi -# opteryx-core execution surface: a Session that yields native -# morsels. `execute_to_morsels` runs entirely in the native engine; draining -# the generator is the execution. We time the drain (matching the engine's own -# ClickBench runner), holding the morsels so results can be emitted afterwards. -# NB: opteryx.query() / Cursor.arrow() from the 0.x line no longer exist here. -session = opteryx.session() -start = timeit.default_timer() -morsels = list(session.execute_to_morsels(query)) -end = timeit.default_timer() - -cols = None -for morsel in morsels: - if cols is None: - cols = morsel.column_names - print("\t".join( - c.decode() if isinstance(c, (bytes, bytearray)) else str(c) - for c in cols - )) - for i in range(morsel.num_rows): - print("\t".join("" if v is None else str(v) for v in morsel[i])) - -session.close() - -print(f"{end - start:.3f}", file=sys.stderr) -PY +cat "$body" +echo "$elapsed" >&2 diff --git a/opteryx/results/20261004/c6a.2xlarge.json b/opteryx/results/20261004/c6a.2xlarge.json new file mode 100644 index 0000000000..4d361397bb --- /dev/null +++ b/opteryx/results/20261004/c6a.2xlarge.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx (Parquet, partitioned)", + "date": "2026-10-04", + "machine": "c6a.2xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 0, + "data_size": 14737666736, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.661, 0.004, 0.003], + [0.928, 0.205, 0.207], + [1.008, 0.314, 0.309], + [1.069, 0.236, 0.231], + [1.8, 1.02, 1.005], + [1.673, 0.829, 0.822], + [0.776, 0.005, 0.004], + [1.027, 0.208, 0.208], + [2.07, 1.168, 1.162], + [2.395, 1.455, 1.447], + [1.157, 0.271, 0.271], + [1.218, 0.293, 0.291], + [1.925, 0.99, 0.977], + [2.915, 1.343, 1.326], + [1.943, 1.108, 1.095], + [1.845, 1.004, 1.002], + [3.214, 2.093, 2.093], + [0.852, 0.033, 0.032], + [5.345, 3.939, 3.978], + [0.972, 0.094, 0.089], + [10.134, 3.251, 3.308], + [11.629, 3.721, 3.745], + [21.808, 5.979, 5.969], + [2.117, 0.807, 0.718], + [0.912, 0.2, 0.192], + [1.422, 0.645, 0.634], + [1.005, 0.204, 0.22], + [10.149, 3.231, 3.252], + [9.33, 5.03, 5.017], + [0.908, 0.208, 0.211], + [2.582, 1.203, 1.185], + [6.246, 1.315, 1.291], + [6.681, 4.569, 4.54], + [10.317, 4.641, 4.626], + [10.352, 4.648, 4.727], + [1.793, 0.965, 0.957], + [0.993, 0.22, 0.201], + [0.808, 0.091, 0.085], + [0.838, 0.067, 0.06], + [1.245, 0.458, 0.385], + [0.889, 0.057, 0.06], + [0.87, 0.06, 0.056], + [0.865, 0.046, 0.045] +] + } + \ No newline at end of file diff --git a/opteryx/results/20261004/c6a.4xlarge.json b/opteryx/results/20261004/c6a.4xlarge.json new file mode 100644 index 0000000000..6c6e4fb46b --- /dev/null +++ b/opteryx/results/20261004/c6a.4xlarge.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx (Parquet, partitioned)", + "date": "2026-10-04", + "machine": "c6a.4xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 0, + "data_size": 14737666736, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.626, 0.004, 0.003], + [0.796, 0.109, 0.109], + [0.967, 0.168, 0.167], + [1.091, 0.152, 0.148], + [1.249, 0.582, 0.604], + [1.467, 0.514, 0.51], + [0.837, 0.004, 0.003], + [0.971, 0.111, 0.11], + [1.67, 0.85, 0.842], + [1.931, 1.047, 1.029], + [1.128, 0.165, 0.166], + [1.004, 0.177, 0.174], + [1.399, 0.672, 0.66], + [2.791, 0.889, 0.889], + [1.424, 0.722, 0.723], + [1.593, 0.691, 0.677], + [2.963, 1.444, 1.427], + [0.696, 0.03, 0.028], + [5.226, 2.802, 2.781], + [0.762, 0.07, 0.066], + [10.108, 2.333, 2.338], + [11.673, 2.654, 2.624], + [21.734, 4.009, 3.944], + [2.131, 0.471, 0.44], + [0.88, 0.167, 0.158], + [1.434, 0.421, 0.422], + [1.002, 0.165, 0.151], + [10.261, 2.404, 2.407], + [9.01, 3.834, 3.8], + [0.767, 0.128, 0.127], + [2.517, 0.743, 0.756], + [6.176, 0.91, 0.909], + [6.462, 3.564, 3.606], + [10.419, 3.522, 3.603], + [10.42, 3.579, 3.59], + [1.373, 0.641, 0.629], + [1.068, 0.205, 0.204], + [0.98, 0.081, 0.084], + [0.988, 0.063, 0.069], + [1.398, 0.4, 0.331], + [0.944, 0.048, 0.049], + [0.941, 0.047, 0.044], + [0.847, 0.044, 0.04] +] + } + \ No newline at end of file diff --git a/opteryx/results/20261004/c6a.large.json b/opteryx/results/20261004/c6a.large.json new file mode 100644 index 0000000000..7bceb6407f --- /dev/null +++ b/opteryx/results/20261004/c6a.large.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx (Parquet, partitioned)", + "date": "2026-10-04", + "machine": "c6a.large", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 0, + "data_size": 14737666736, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.749, 0.004, 0.003], + [1.602, 0.844, 0.84], + [2.039, 1.259, 1.25], + [1.775, 0.935, 0.895], + [4.42, 3.431, 3.422], + [4.081, 3.082, 3.124], + [0.805, 0.004, 0.004], + [1.699, 0.841, 0.846], + [4.713, 3.274, 3.226], + [6.118, 4.518, 4.498], + [2.051, 0.981, 0.981], + [2.129, 1.091, 1.102], + [4.976, 3.516, 3.459], + [6.478, 4.857, 4.736], + [5.447, 3.892, 3.81], + [4.7, 3.338, 3.228], + [13.804, 42.473, 71.203], + [0.885, 0.091, 0.091], + [91.679, 466.856, 567.886], + [1.199, 0.294, 0.291], + [13.98, 12.806, 13.582], + [16.058, 15.219, 16.042], + [26.124, 25.74, 26.344], + [3.235, 1.972, 1.908], + [1.593, 0.666, 0.702], + [3.437, 2.449, 2.426], + [1.58, 0.691, 0.698], + [13.614, 12.416, 13.015], + [43.709, 49.262, 71.182], + [1.542, 0.743, 0.739], + [5.694, 4.293, 4.301], + [6.721, 4.39, 4.428], + [212.635, 596.342, 623.523], + [56.426, 383.034, 506.725], + [82.614, 801.51, 1008.018], + [4.298, 3.066, 3.027], + [1.22, 0.37, 0.373], + [0.914, 0.142, 0.141], + [0.88, 0.12, 0.118], + [1.548, 0.583, 0.581], + [0.942, 0.093, 0.087], + [0.932, 0.089, 0.085], + [0.936, 0.08, 0.082] +] + } + \ No newline at end of file diff --git a/opteryx/results/20261004/c6a.metal.json b/opteryx/results/20261004/c6a.metal.json new file mode 100644 index 0000000000..535ff3e3de --- /dev/null +++ b/opteryx/results/20261004/c6a.metal.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx (Parquet, partitioned)", + "date": "2026-10-04", + "machine": "c6a.metal", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 0, + "data_size": 14737666736, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.713, 0.008, 0.006], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [0.711, 0.008, 0.006], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null] +] + } + \ No newline at end of file diff --git a/opteryx/results/20261004/c6a.xlarge.json b/opteryx/results/20261004/c6a.xlarge.json new file mode 100644 index 0000000000..9f359a6950 --- /dev/null +++ b/opteryx/results/20261004/c6a.xlarge.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx (Parquet, partitioned)", + "date": "2026-10-04", + "machine": "c6a.xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 0, + "data_size": 14737666736, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.592, 0.004, 0.004], + [1.04, 0.41, 0.408], + [1.392, 0.616, 0.613], + [1.407, 0.442, 0.436], + [2.746, 1.853, 1.881], + [2.496, 1.525, 1.539], + [0.788, 0.004, 0.004], + [1.24, 0.413, 0.414], + [2.843, 1.792, 1.747], + [3.477, 2.385, 2.33], + [1.511, 0.478, 0.488], + [1.597, 0.541, 0.535], + [2.838, 1.731, 1.729], + [3.693, 2.391, 2.357], + [3.059, 1.962, 1.942], + [2.815, 1.735, 1.679], + [5.018, 3.668, 3.592], + [0.886, 0.053, 0.05], + [12.535, 67.797, 112.399], + [0.88, 0.149, 0.14], + [10.125, 5.915, 5.929], + [11.495, 6.804, 6.773], + [21.699, 11.132, 11.138], + [2.236, 1.074, 0.998], + [1.224, 0.354, 0.356], + [2.145, 1.186, 1.208], + [1.226, 0.342, 0.349], + [10.155, 5.811, 5.843], + [10.455, 8.702, 8.677], + [1.181, 0.37, 0.371], + [3.354, 2.163, 2.175], + [6.459, 2.256, 2.248], + [36.679, 171.219, 186.556], + [11.014, 124.472, 232.737], + [17.915, 112.415, 346.251], + [2.469, 1.658, 1.645], + [1.142, 0.255, 0.225], + [0.959, 0.1, 0.086], + [0.96, 0.071, 0.08], + [1.408, 0.446, 0.423], + [0.909, 0.063, 0.059], + [0.902, 0.054, 0.053], + [0.895, 0.055, 0.055] +] + } + \ No newline at end of file diff --git a/opteryx/results/20261004/c7a.metal-48xl.json b/opteryx/results/20261004/c7a.metal-48xl.json new file mode 100644 index 0000000000..38908aa945 --- /dev/null +++ b/opteryx/results/20261004/c7a.metal-48xl.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx (Parquet, partitioned)", + "date": "2026-10-04", + "machine": "c7a.metal-48xl", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 0, + "data_size": 14737666736, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.709, 0.007, 0.007], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [0.708, 0.007, 0.006], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null] +] + } + \ No newline at end of file diff --git a/opteryx/results/20261004/c8g.4xlarge.json b/opteryx/results/20261004/c8g.4xlarge.json new file mode 100644 index 0000000000..492d97ffc5 --- /dev/null +++ b/opteryx/results/20261004/c8g.4xlarge.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx (Parquet, partitioned)", + "date": "2026-10-04", + "machine": "c8g.4xlarge", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 0, + "data_size": 14737666736, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.564, 0.004, 0.003], + [0.642, 0.053, 0.056], + [0.66, 0.088, 0.084], + [0.861, 0.069, 0.067], + [0.943, 0.253, 0.262], + [1.229, 0.234, 0.231], + [0.58, 0.004, 0.003], + [0.645, 0.055, 0.056], + [1.36, 0.508, 0.505], + [1.563, 0.62, 0.596], + [0.902, 0.081, 0.079], + [0.947, 0.091, 0.089], + [1.275, 0.291, 0.282], + [2.585, 0.372, 0.368], + [1.302, 0.305, 0.306], + [0.96, 0.257, 0.254], + [2.612, 0.534, 0.526], + [0.592, 0.018, 0.016], + [4.634, 0.997, 0.962], + [0.732, 0.033, 0.035], + [9.979, 1.12, 1.087], + [11.591, 1.219, 1.214], + [21.88, 1.909, 1.845], + [2.074, 0.34, 0.342], + [0.73, 0.088, 0.084], + [1.242, 0.195, 0.191], + [0.703, 0.083, 0.084], + [9.983, 1.045, 1.072], + [8.776, 1.55, 1.554], + [0.685, 0.079, 0.079], + [2.471, 0.338, 0.347], + [6.093, 0.358, 0.356], + [5.044, 1.06, 1.044], + [10.108, 1.391, 1.394], + [10.128, 1.433, 1.371], + [0.898, 0.265, 0.266], + [0.808, 0.158, 0.149], + [0.689, 0.07, 0.068], + [0.697, 0.052, 0.051], + [0.993, 0.261, 0.288], + [0.667, 0.04, 0.037], + [0.709, 0.037, 0.035], + [0.711, 0.036, 0.036] +] + } + \ No newline at end of file diff --git a/opteryx/results/20261004/c8g.metal-48xl.json b/opteryx/results/20261004/c8g.metal-48xl.json new file mode 100644 index 0000000000..d49c296c2e --- /dev/null +++ b/opteryx/results/20261004/c8g.metal-48xl.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx (Parquet, partitioned)", + "date": "2026-10-04", + "machine": "c8g.metal-48xl", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 0, + "data_size": 14737666736, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.529, 0.004, 0.003], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [0.623, 0.004, 0.003], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null] +] + } + \ No newline at end of file diff --git a/opteryx/results/20261004/t3a.small.json b/opteryx/results/20261004/t3a.small.json new file mode 100644 index 0000000000..25e60c6bc3 --- /dev/null +++ b/opteryx/results/20261004/t3a.small.json @@ -0,0 +1,60 @@ +{ + "system": "Opteryx (Parquet, partitioned)", + "date": "2026-10-04", + "machine": "t3a.small", + "cluster_size": 1, + "proprietary": "no", + "hardware": "cpu", + "tuned": "no", + "tags": ["C++","stateless","column-oriented","embedded"], + "load_time": 0, + "data_size": 14737666736, + "concurrent_qps": null, + "concurrent_error_ratio": null, + "result": [ + [0.893, 0.007, 0.006], + [2.204, 1.277, 1.284], + [2.873, 1.918, 1.89], + [2.467, 1.34, 1.372], + [7.181, 5.836, 5.789], + [6.835, 5.51, 5.504], + [0.991, 0.008, 0.007], + [2.301, 1.391, 1.299], + [8.271, 6.666, 6.889], + [9.986, 8.567, 9.363], + [2.785, 1.528, 1.528], + [2.993, 1.733, 1.749], + [8.222, 11.032, 16.024], + [32.875, 77.536, 108.649], + [8.916, 13.027, 24.968], + [11.704, 16.419, 34.201], + [50.189, 226.091, 276.194], + [1.091, 0.147, 0.147], + [162.834, 621.717, 667.587], + [1.482, 0.442, 0.461], + [24.482, 24.871, 28.422], + [29.192, 29.744, 30.52], + [46.665, 47.937, 47.453], + [5.15, 3.624, 3.503], + [2.171, 1.132, 1.125], + [5.454, 4.148, 4.148], + [2.259, 1.179, 1.199], + [25.849, 25.058, 25.503], + [112.782, 198.337, 201.728], + [2.05, 1.171, 1.16], + [9.986, 11.568, 11.5], + [21.938, 49.254, 68.239], + [308.888, 767.498, 1455.112], + [148.811, 1109.802, 1236.075], + [150.419, 1063.018, 1242.953], + [7.992, 6.668, 7.504], + [1.787, 0.662, 0.641], + [1.265, 0.252, 0.252], + [1.283, 0.214, 0.205], + [2.24, 1.073, 0.992], + [1.191, 0.149, 0.148], + [1.226, 0.147, 0.139], + [1.235, 0.141, 0.139] +] + } + \ No newline at end of file diff --git a/opteryx/server.py b/opteryx/server.py new file mode 100644 index 0000000000..ba89e1eeb8 --- /dev/null +++ b/opteryx/server.py @@ -0,0 +1,82 @@ +""" +Long-lived Opteryx query server for the ClickBench entry. + +Standard library only — the venv holds opteryx-core and nothing else. + +Routes (127.0.0.1:8421): + GET /health -> 200, body = opteryx version. No query is run: ./check + calls this before every cold try, and a query here would + warm the engine ahead of the measurement. + POST /query -> body = one SQL statement. Response body = the result as + TSV (header + rows); header X-Elapsed = seconds spent + draining execute_to_morsels. + +The clock covers exactly what the embedded entry's clock covered: draining +`execute_to_morsels`. Session construction (warm: ~0.04ms) and TSV rendering +are outside it. + +One session per request; the engine's footer and schema caches are process +scoped, so tries 2..3 of a query see a warm process. There is no result cache. + +A query that raises is not caught: the handler dies, the connection closes with +no response, `./query` exits non-zero and the driver records null. The traceback +is in server.log. +""" + +import timeit +from http.server import BaseHTTPRequestHandler +from http.server import HTTPServer + +import opteryx + +HOST = "127.0.0.1" +PORT = 8421 + + +def render_tsv(morsels) -> bytes: + lines = [] + for morsel in morsels: + if not lines: + lines.append("\t".join(c.decode() for c in morsel.column_names)) + for i in range(morsel.num_rows): + lines.append("\t".join("" if v is None else str(v) for v in morsel[i])) + return ("\n".join(lines) + "\n").encode() if lines else b"" + + +class Handler(BaseHTTPRequestHandler): + def do_GET(self): + if self.path != "/health": + self.send_error(404) + return + body = opteryx.__version__.encode() + self.send_response(200) + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + def do_POST(self): + if self.path != "/query": + self.send_error(404) + return + query = self.rfile.read(int(self.headers["Content-Length"])).decode() + + session = opteryx.session() + start = timeit.default_timer() + morsels = list(session.execute_to_morsels(query)) + elapsed = timeit.default_timer() - start + + body = render_tsv(morsels) + session.close() + + self.send_response(200) + self.send_header("X-Elapsed", f"{elapsed:.6f}") + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + def log_message(self, format, *args): + pass + + +if __name__ == "__main__": + HTTPServer((HOST, PORT), Handler).serve_forever() diff --git a/opteryx/start b/opteryx/start index 06bd986563..277fdafc80 100755 --- a/opteryx/start +++ b/opteryx/start @@ -1,2 +1,11 @@ #!/bin/bash -exit 0 +# Launch the long-lived query server and nothing else: no warm-up query, no +# touching the dataset. ./check is the readiness signal. +set -e + +if [ -f server.pid ] && kill -0 "$(cat server.pid)" 2>/dev/null; then + exit 0 +fi + +nohup "$HOME/opteryx_venv/bin/python" server.py >>server.log 2>&1 & +echo $! > server.pid diff --git a/opteryx/stop b/opteryx/stop index 06bd986563..1de5ad6a88 100755 --- a/opteryx/stop +++ b/opteryx/stop @@ -1,2 +1,12 @@ #!/bin/bash +# The driver waits for ./check to fail after this, so the process must be gone, +# not just signalled. +if [ -f server.pid ]; then + pid=$(cat server.pid) + kill "$pid" 2>/dev/null || true + while kill -0 "$pid" 2>/dev/null; do + sleep 0.1 + done + rm -f server.pid +fi exit 0