Add Rayforce - #1375
Open
alexey-milovidov wants to merge 1 commit into
Open
Conversation
Rayforce (https://github.com/RayforceDB/rayforce) is a zero-dependency columnar analytics and graph engine in pure C, queried through Rayfall, its Lisp-like language. queries.sql therefore holds 43 Rayfall expressions, one per line, the way jd/bqn hold their own dialects. (Not to be confused with the closed #940, which was RayforceDB's internal 10M-row harness opened against this repo by mistake.) Two measured engine properties shaped the entry: - Text columns are loaded as SYM (dictionary-encoded), not STR. STR pool offsets are uint32_t, so a column's pool is capped at 4 GiB, and at 100M rows URL/Title/Referer/OriginalURL need 5-11 GB each. Opening a splayed table also validates every STR element, and that cost is superlinear: 0.4 s at 2M rows, 199 s at 9.6M rows (99 s for the parted layout). All-SYM opens in 17 s at 9.6M rows and stores the same subset in 4.4 GB instead of 7.5 GB. - It runs as an IPC server, with BENCH_RESTARTABLE=yes. Opening the table is eager (validate every column file, load the dictionary), so a CLI-per-query would pay that 129 times per run; the server pays it once per start and times queries with `timeit` server-side. The restart is not optional either: with the server left up, drop_caches cannot evict pages a live process still maps, and a "cold" query measured 0.029 s against 0.44 s after a real restart, so keeping the process alive would report every run as warm. BENCH_CHECK_TIMEOUT is raised to 1800 s because the readiness probe now waits for that table open. Query notes: HAVING becomes an outer select over the grouped one; LIMIT/OFFSET is take: [m n]; DATE_TRUNC('minute', EventTime) is (xbar EventTime 60000000000); CASE WHEN is the row-wise (if ...); Q29's REGEXP_REPLACE is rebuilt from str-find/substr/if and reproduces the regex exactly on this dataset, fallback rows included. Q25/Q27 project EventTime alongside SearchPhrase because sorting runs after projection, and Q35 projects the constant group key in an outer select. All 43 queries were checked against clickhouse-local on a 2M-row subset of the same CSV: 33 match exactly or modulo row order, and the other 10 differ only in which of several equally-ranked rows a LIMIT over ties returns (the sort-key multisets are identical). install, load, the stop/drop_caches/start/check cold cycle, 43 queries through ./query, 10 concurrent clients and the error paths were all exercised end to end. Two upstream bugs found on the way, neither affecting this entry: RayforceDB/rayforce#404 (take: drops pool-backed STR values) and RayforceDB/rayforce#405 (ungrouped count(distinct) in a select projection returns the row count). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds Rayforce — a zero-dependency
columnar analytics and graph engine in pure C (MIT), queried through Rayfall,
its Lisp-like language.
queries.sqltherefore holds 43 Rayfall expressions,one per line, the way
jdandbqnhold their own dialects.(Not the same as the closed #940 — that was RayforceDB's internal 10M-row
harness, opened against this repo by mistake. This is a standard-harness entry
on the full dataset.)
Two measured engine properties shaped the entry
Text columns load as
SYM(dictionary-encoded), notSTR.STRpooloffsets are
uint32_t, so a column's pool is capped at 4 GiB, while at 100Mrows
URL/Title/Referer/OriginalURLhold 5–11 GB of bytes each. Opening asplayed table also validates every
STRelement, and that cost is superlinear:0.4 s at 2M rows, 199 s at 9.6M rows (99 s for the parted layout). All-
SYMopens in 17 s at 9.6M rows and stores the same subset in 4.4 GB instead of
7.5 GB.
It runs as an IPC server, with
BENCH_RESTARTABLE=yes. The table open iseager (validate every column file, load the dictionary), so a CLI-per-query
would pay it 129 times per run; the server pays it once per start and times
queries with
timeitserver-side. The restart is not optional either: with theserver left up,
drop_cachescannot evict pages a live process still maps, anda "cold" query measured 0.029 s versus 0.44 s after a real restart — keeping the
process alive would report every run as warm.
BENCH_CHECK_TIMEOUTis raised to1800 s because the readiness probe now waits for that open.
Query notes
HAVINGbecomes an outerselectover the grouped one;LIMIT n OFFSET mistake: [m n];DATE_TRUNC('minute', EventTime)is(xbar EventTime 60000000000);CASE WHENis the row-wise(if ...). Q29'sREGEXP_REPLACEis rebuilt fromstr-find/substr/ifand reproduces theregex exactly on this dataset, fallback rows included. Q25/Q27 project
EventTimealongsideSearchPhrasebecause sorting runs after projection, andQ35 projects its constant group key in an outer
select.Validation
All 43 queries were diffed against
clickhouse-localon a 2M-row subset of thesame CSV: 33 match exactly or modulo row order, and the other 10 differ only in
which of several equally-ranked rows a
LIMITover ties returns (the sort-keymultisets are identical).
install,load, the stop/drop_caches/start/checkcold cycle, all 43 queries through
./query, 10 concurrent clients, and theerror paths were exercised end to end.
Upstream bugs found on the way
Neither affects this entry, both filed with minimal repros:
selectwithtake:returns empty strings forpool-backed
STRvalues (silently;(select {from: t take: 1})is enough).A further reason the text columns here are
SYM.(count (distinct col))in aselectprojection returns the row count on
STR/SYMand a type error on integers;hence Q5/Q6 use the whole-column reducer
(count (distinct (at hits 'c))).🤖 Generated with Claude Code