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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions rayforce/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,21 @@ unset, it takes the latest GitHub release.

## Data layout

`./load` streams `hits.csv` into a splayed on-disk table under `./hits`
with `.csv.splayed` — one file per column plus the `.sym` dictionary,
parsed in parallel from an mmap of the CSV without materializing the
table in memory. The column names come from `create.rfl`; passing an
explicit name vector also tells the reader the input has no header row,
which is the shape of the published `hits.csv`.
`./load` streams `hits.parquet` into a splayed on-disk table under
`./hits` with `.parquet.splayed` — one file per column plus the `.sym`
dictionary, written row group by row group without materializing the
table in memory. The column names come from the file; `create.rfl`
gives the native type of each column in the file's order.

Types follow `../clickhouse/create.sql`: `BIGINT` → `I64`, `INTEGER` →
`I32`, `SMALLINT` → `I16`, `TIMESTAMP` → `TIMESTAMP`, `Date` → `DATE`.
Rayforce's CSV reader parses the `YYYY-MM-DD` and `YYYY-MM-DD HH:MM:SS`
forms in the file into its native date/timestamp types, so
`EventDate >= '2013-07-01'`, `extract(minute FROM EventTime)` and
`DATE_TRUNC('minute', EventTime)` all work on native values.
The Parquet file keeps `EventDate` as integer days since 1970-01-01 and
`EventTime`, `ClientEventTime` and `LocalEventTime` as integer Unix
seconds; their entries in the type vector, `UNIX_DATE` and
`UNIX_SECONDS`, make the reader convert them to Rayforce's native date
and timestamp types, so `EventDate >= '2013-07-01'`,
`extract(minute FROM EventTime)` and `DATE_TRUNC('minute', EventTime)`
all work on native values.

### Why every text column is SYM

Expand Down
2 changes: 1 addition & 1 deletion rayforce/benchmark.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
export BENCH_DOWNLOAD_SCRIPT="download-hits-csv"
export BENCH_DOWNLOAD_SCRIPT="download-hits-parquet-single"
# Rayforce runs as an IPC server here (./start), so the stop/drop_caches/start
# cold cycle is meaningful and the concurrent-QPS test hits a shared process.
export BENCH_RESTARTABLE=yes
Expand Down
21 changes: 12 additions & 9 deletions rayforce/create.rfl
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
; ClickBench `hits` schema for Rayforce.
;
; `load` feeds these two vectors to `.csv.splayed`, which streams
; hits.csv straight into the on-disk splayed table without a header row
; (an explicit name vector implies headerless input).
; `load` passes `hits-types` to `.parquet.splayed`, one entry per column
; of hits.parquet in file order; `hits-names` lists that order.
;
; Types follow ../clickhouse/create.sql: BIGINT -> I64, INTEGER -> I32,
; SMALLINT -> I16, TIMESTAMP -> TIMESTAMP, Date -> DATE. Every TEXT /
; VARCHAR / CHAR column is loaded as SYM (dictionary-encoded) rather
; than STR -- see README.md "Why every text column is SYM".
; SMALLINT -> I16, TIMESTAMP -> TIMESTAMP, Date -> DATE. The Parquet
; file keeps EventDate as integer days since 1970-01-01 and EventTime,
; ClientEventTime and LocalEventTime as integer Unix seconds: UNIX_DATE
; and UNIX_SECONDS make the reader convert them to native DATE and
; TIMESTAMP. Every TEXT / VARCHAR / CHAR column is loaded as SYM
; (dictionary-encoded) rather than STR -- see README.md "Why every text
; column is SYM".

(set hits-names [
WatchID JavaEnable Title GoodEvent EventTime EventDate CounterID ClientIP
Expand All @@ -32,10 +35,10 @@
])

(set hits-types [
I64 I16 SYM I16 TIMESTAMP DATE I32 I32 I32 I64 I16 I16 I16 SYM SYM I16
I64 I16 SYM I16 UNIX_SECONDS UNIX_DATE I32 I32 I32 I64 I16 I16 I16 SYM SYM I16
I16 I32 I16 I32 I16 I16 I16 I16 I16 SYM I16 I16 I16 SYM I16 I16 I16 I16
SYM SYM I32 I16 I16 SYM I16 I16 I16 I16 I16 TIMESTAMP I16 I16 I32 I16 SYM
I32 I16 I16 I16 I64 SYM I32 I16 I16 I16 I16 I16 SYM TIMESTAMP I16 I16 I16
SYM SYM I32 I16 I16 SYM I16 I16 I16 I16 I16 UNIX_SECONDS I16 I16 I32 I16 SYM
I32 I16 I16 I16 I64 SYM I32 I16 I16 I16 I16 I16 SYM UNIX_SECONDS I16 I16 I16
I16 I16 I32 I32 I32 I16 SYM SYM SYM SYM I16 I32 I32 I32 I32 I32 I32 I16
SYM I64 SYM SYM I16 SYM SYM SYM SYM SYM SYM SYM SYM SYM SYM I16 I64 I64
I32
Expand Down
2 changes: 1 addition & 1 deletion rayforce/install
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# (falling back to a known-good tag when the unauthenticated API call is rate
# limited).
#
# Last benchmarked release: v2.10.0. Bump this line to request a new run:
# Last benchmarked release: v2.11.0. Bump this line to request a new run:
# the benchmark automation reruns a system when a file in its directory
# changes.
set -e
Expand Down
6 changes: 3 additions & 3 deletions rayforce/load
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# Loads hits.csv into the splayed table ./hits.
# Loads hits.parquet into the splayed table ./hits.
#
# The load runs in its own rayforce process, not through the server: the server
# started by the driver before ./load has no table open yet and picks it up at
Expand All @@ -10,6 +10,6 @@ rm -rf hits

rayforce load.rfl

# The CSV is no longer needed once the columns are on disk.
rm -f hits.csv
# The Parquet file is no longer needed once the columns are on disk.
rm -f hits.parquet
sync
10 changes: 5 additions & 5 deletions rayforce/load.rfl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
; Stream hits.csv into a splayed on-disk table under ./hits.
; Stream hits.parquet into a splayed on-disk table under ./hits.
;
; `.csv.splayed` mmaps the CSV, parses chunks in parallel and writes one column
; `.parquet.splayed` reads the file row group by row group and writes one column
; file per field plus the `.sym` dictionary, without materialising the whole
; table in memory. The name vector implies the input has no header row, which is
; the shape of the published hits.csv.
; table in memory. The column names come from the file; `hits-types` gives the
; native type of each column in the file's order.
(load "create.rfl")
(.csv.splayed hits-names hits-types "hits.csv" "hits")
(.parquet.splayed hits-types "hits.parquet" "hits")
(exit 0)
60 changes: 60 additions & 0 deletions rayforce/results/20261004/c6a.2xlarge.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"system": "Rayforce",
"date": "2026-10-04",
"machine": "c6a.2xlarge",
"cluster_size": 1,
"proprietary": "no",
"hardware": "cpu",
"tuned": "no",
"tags": ["C","column-oriented","embedded"],
"load_time": 1106,
"data_size": 59042332197,
"concurrent_qps": 0.21,
"concurrent_error_ratio": 0,
"result": [
[0, 0, 0],
[0.175, 0.01, 0.01],
[0.006, 0, 0],
[2.072, 0.021, 0.02],
[2.578, 0.465, 0.485],
[1.714, 0.119, 0.118],
[0.006, 0, 0],
[0.181, 0.018, 0.018],
[5.878, 1.84, 1.84],
[6.709, 1.334, 1.27],
[3.72, 0.137, 0.131],
[4.491, 0.141, 0.141],
[0.745, 0.177, 0.178],
[3.997, 0.401, 0.413],
[1.504, 0.212, 0.207],
[3.238, 1.002, 0.967],
[7.017, 1.775, 1.362],
[8.86, 0.042, 0.042],
[8.97, 2.256, 2.202],
[0.022, 0, 0],
[0.63, 0.332, 0.334],
[2.08, 0.178, 0.175],
[4.239, 0.467, 0.474],
[0.891, 0.039, 0.037],
[0.099, 0.004, 0.005],
[0.536, 0.129, 0.124],
[0.105, 0.005, 0.005],
[2.807, 0.854, 0.845],
[3.218, 3.207, 2.841],
[0.018, 0, 0],
[4.473, 0.278, 0.278],
[7.037, 0.385, 0.364],
[39.572, 54.658, 141.651],
[1.062, 0.517, 0.528],
[1.066, 0.514, 0.517],
[1.462, 0.978, 0.976],
[0.073, 0.024, 0.024],
[0.071, 0.024, 0.024],
[0.091, 0.014, 0.013],
[0.136, 0.084, 0.064],
[0.263, 0.015, 0.015],
[0.062, 0.006, 0.006],
[0.068, 0.013, 0.013]
]
}

60 changes: 60 additions & 0 deletions rayforce/results/20261004/c6a.4xlarge.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"system": "Rayforce",
"date": "2026-10-04",
"machine": "c6a.4xlarge",
"cluster_size": 1,
"proprietary": "no",
"hardware": "cpu",
"tuned": "no",
"tags": ["C","column-oriented","embedded"],
"load_time": 518,
"data_size": 59042332197,
"concurrent_qps": 0.775,
"concurrent_error_ratio": 0,
"result": [
[0, 0, 0],
[0.569, 0.005, 0.005],
[0.007, 0, 0],
[2.07, 0.02, 0.02],
[2.396, 0.209, 0.209],
[1.774, 0.105, 0.104],
[0.008, 0, 0],
[0.181, 0.011, 0.011],
[5.568, 0.846, 0.843],
[5.931, 0.536, 0.524],
[3.67, 0.091, 0.09],
[4.445, 0.103, 0.101],
[0.846, 0.113, 0.113],
[3.869, 0.282, 0.278],
[1.436, 0.138, 0.134],
[2.566, 0.406, 0.406],
[4.408, 0.854, 0.855],
[9.243, 0.031, 0.031],
[7.923, 1.299, 1.32],
[0.022, 0, 0],
[0.567, 0.174, 0.173],
[2.082, 0.104, 0.104],
[4.136, 0.223, 0.223],
[0.875, 0.017, 0.018],
[0.084, 0.003, 0.003],
[0.538, 0.063, 0.063],
[0.07, 0.005, 0.003],
[2.457, 0.452, 0.452],
[2.62, 2.105, 2.108],
[0.019, 0, 0],
[4.442, 0.176, 0.175],
[6.81, 0.249, 0.248],
[7.031, 2.139, 1.961],
[0.89, 0.274, 0.281],
[0.889, 0.274, 0.28],
[0.995, 0.37, 0.369],
[0.068, 0.021, 0.021],
[0.069, 0.02, 0.021],
[0.092, 0.012, 0.011],
[0.125, 0.071, 0.051],
[0.192, 0.015, 0.015],
[0.061, 0.007, 0.006],
[0.06, 0.01, 0.01]
]
}

60 changes: 60 additions & 0 deletions rayforce/results/20261004/c6a.metal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"system": "Rayforce",
"date": "2026-10-04",
"machine": "c6a.metal",
"cluster_size": 1,
"proprietary": "no",
"hardware": "cpu",
"tuned": "no",
"tags": ["C","column-oriented","embedded"],
"load_time": 258,
"data_size": 59042332197,
"concurrent_qps": 7.483,
"concurrent_error_ratio": 0,
"result": [
[0, 0, 0],
[0.094, 0.004, 0.004],
[0.006, 0, 0],
[2.083, 0.011, 0.011],
[2.234, 0.123, 0.12],
[1.68, 0.115, 0.12],
[0.006, 0, 0],
[0.148, 0.01, 0.013],
[5.09, 0.145, 0.148],
[5.819, 0.336, 0.316],
[3.729, 0.067, 0.071],
[4.465, 0.066, 0.065],
[0.683, 0.079, 0.077],
[3.798, 0.161, 0.165],
[1.431, 0.085, 0.087],
[2.441, 0.232, 0.241],
[3.887, 0.226, 0.22],
[9.294, 0.019, 0.018],
[7.07, 0.373, 0.377],
[0.036, 0.001, 0.001],
[0.577, 0.091, 0.092],
[2.098, 0.128, 0.072],
[3.992, 0.182, 0.149],
[0.579, 0.016, 0.02],
[0.064, 0.003, 0.003],
[0.552, 0.025, 0.023],
[0.066, 0.002, 0.003],
[2.651, 0.615, 0.567],
[2.222, 1.632, 1.87],
[0.032, 0, 0],
[4.486, 0.116, 0.13],
[6.814, 0.167, 0.158],
[5.873, 0.767, 0.756],
[0.879, 0.276, 0.247],
[0.912, 0.407, 0.238],
[0.848, 0.185, 0.208],
[0.136, 0.026, 0.043],
[0.146, 0.025, 0.04],
[0.165, 0.016, 0.023],
[0.193, 0.092, 0.073],
[0.211, 0.029, 0.024],
[0.11, 0.023, 0.021],
[0.12, 0.014, 0.015]
]
}

60 changes: 60 additions & 0 deletions rayforce/results/20261004/c6a.xlarge.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"system": "Rayforce",
"date": "2026-10-04",
"machine": "c6a.xlarge",
"cluster_size": 1,
"proprietary": "no",
"hardware": "cpu",
"tuned": "no",
"tags": ["C","column-oriented","embedded"],
"load_time": 3351,
"data_size": 59042332197,
"concurrent_qps": 0.058,
"concurrent_error_ratio": 0.667,
"result": [
[0, 0, 0],
[0.331, 0.02, 0.02],
[0.006, 0, 0],
[2.069, 0.022, 0.021],
[2.796, 0.678, 0.704],
[1.705, 0.111, 0.11],
[0.007, 0, 0],
[0.314, 0.033, 0.032],
[93.218, 3.544, 2.984],
[11.594, 3.723, 2.709],
[3.8, 0.21, 0.214],
[4.585, 0.234, 0.234],
[1.048, 0.309, 0.306],
[4.555, 0.904, 0.858],
[1.686, 0.368, 0.363],
[7.671, 5.523, 3.049],
[11.25, 3.118, 2.339],
[8.839, 0.08, 0.08],
[43.684, 154.708, 277.965],
[0.024, 0, 0],
[13.923, 9.518, 1.516],
[11.638, 0.733, 0.296],
[21.926, 11.274, 1.225],
[2.759, 0.067, 0.062],
[0.166, 0.008, 0.008],
[2, 0.252, 0.256],
[0.165, 0.01, 0.009],
[24.463, 7.359, 1.679],
[26.594, 38.579, 25.658],
[0.02, 0, 0],
[4.59, 0.667, 0.639],
[9.478, 6.284, 0.948],
[208.128, 254.53, 442.923],
[4.807, 2.469, 1.802],
[4.854, 12.698, 2.728],
[2.519, 1.848, 1.717],
[0.095, 0.034, 0.033],
[0.084, 0.028, 0.028],
[0.094, 0.017, 0.017],
[0.343, 0.111, 0.084],
[0.426, 0.017, 0.017],
[0.07, 0.007, 0.007],
[0.088, 0.02, 0.02]
]
}

Loading
Loading