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
11 changes: 10 additions & 1 deletion benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,15 @@ These inputs establish correctness conditions, not performance results.
| Repeated deletion/recreation | `repeated-deletion-recreation-{rows,branches}` | Four bounded cycles followed by the next insertion or branch creation. Every cycle verifies exact rows; the final branch inventory and reopened views are checked. Row churn and branch churn are separate treatments. |
| Threshold crossings | `threshold-crossings-{before,at,after,production-control}` | A configured history-release boundary: two, three, or four updates at `history_release_bytes = 2048`, plus a three-update control at the production budget 262144, followed by an insert. Exact main/child contents are checked. |
| Equal current state, different history | `equal-current-{narrow-one-batch,wide-one-batch,wide-four-batches}` | Four identical final rows after eight past/restore cycles. Prior payload width varies from 8 to 4096 bytes; a separate treatment publishes each load in four batches. Build witnesses check equal current contents and 18/18/66 reachable commits. |
| Unattached branch root write (group `unattached-writes`, with `tiny-mutate-unattached`) | `very-long-history-32-write-unattached`, `unattached-chain-32-write` | The history checkpoint's next update written `as unattached branch` instead of on `main`: the row is checked at the snapshot before and after a restart, `main` keeps the fixture's value, and the snapshot is dropped. The chain case keeps the same 32 updates as one retained unattached chain (a root and 31 children) with `main` at the seed. Each twin pairs with the ordinary write on the same fixture (`very-long-history-32-write`, `tiny-mutate`). |

An unattached record costs the root write only. A child `on` an earlier
snapshot cannot be the selected step: its base id is bound by a write earlier
in the same program, and writes before the selected step are refused. The
engine's per-phase attribution covers `branch merge` only, so these mutation
records carry elapsed time and logical store calls, not a publication or
history-settlement phase split. Neither path's number stands in for a chained
stream or for end-to-end published-write latency.

The threshold fixtures preserve the configured shapes from the engine's
history-release correctness cases. Their row assertions do not prove that a
Expand All @@ -182,7 +191,7 @@ Dataset and query basenames use the same scenario names with underscores.
The history operations share `workloads/very_long_history_{read,write,reopen}.gqt`
across depths, and equal-current cases share
`workloads/equal_current_different_history.gqt`. The owning benchmark catalog
test executes all 20 bounded pairs through dataset construction and the
test executes all 20 bounded pairs, plus the two unattached twins, through dataset construction and the
measured adapter, including their explicit restart verification. Parsing and
suite admission also cover the larger recipes without executing them.

Expand Down
28 changes: 28 additions & 0 deletions benchmarks/benchmarks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,14 @@ scenarios:
text: |
--- mutate
query add() { insert Item { key: "c", val: 3 } }
- id: tiny-mutate-unattached
fixture: fixtures/tiny_graph.gqt
workload: workloads/tiny_mutate_unattached.gqt
measured_step:
ordinal: 1
text: |
--- mutate
query add() as unattached branch { insert Item { key: "c", val: 3 } }
- id: tiny-post-reopen
fixture: fixtures/tiny_graph.gqt
workload: workloads/tiny_post_reopen.gqt
Expand Down Expand Up @@ -385,6 +393,22 @@ scenarios:
text: |
--- mutate
query next_write() { update HistoryRow set { value: 1 } where key = "hot" }
- id: very-long-history-32-write-unattached
fixture: fixtures/very_long_history_32.gqt
workload: workloads/very_long_history_write_unattached.gqt
measured_step:
ordinal: 1
text: |
--- mutate
query next_write() as unattached branch { update HistoryRow set { value: 1 } where key = "hot" }
- id: unattached-chain-32-write
fixture: fixtures/unattached_chain_32.gqt
workload: workloads/very_long_history_write_unattached.gqt
measured_step:
ordinal: 1
text: |
--- mutate
query next_write() as unattached branch { update HistoryRow set { value: 1 } where key = "hot" }
- id: e2e-merge-all-changed
fixture: fixtures/e2e_merge_all_changed.gqt
workload: workloads/e2e_merge_all_changed.gqt
Expand Down Expand Up @@ -1129,6 +1153,10 @@ groups:
- equal-current-wide-four-batches
local-smoke:
- branch-merge-d50-warm
unattached-writes:
- tiny-mutate-unattached
- very-long-history-32-write-unattached
- unattached-chain-32-write
search:
- nearest-ranks-updated-embedding
- nearest-skips-deleted-rows-and-fills-limit
Expand Down
194 changes: 194 additions & 0 deletions benchmarks/fixtures/unattached_chain_32.gqt
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# issue: none
# notes: The 32 paired updates of very_long_history_32 as one retained unattached chain (a root and
# notes: 31 children, each on the previous snapshot); main stays at the seed. The chain is unrolled
# notes: because a commit binding may not sit in a loop.

--- runner
timeout_ms: 60000
environments:
- target: omnigraph-engine
storage: local-filesystem

--- schema
node HistoryRow { key: String @key value: I64 payload: String }

--- seed
{"type":"HistoryRow","data":{"key":"hot","value":0,"payload":"fixed"}}

--- mutate
query set_one() as unattached branch { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c00

--- mutate
query restore_zero() as unattached branch on "${c00}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c01

--- mutate
query set_one() as unattached branch on "${c01}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c02

--- mutate
query restore_zero() as unattached branch on "${c02}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c03

--- mutate
query set_one() as unattached branch on "${c03}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c04

--- mutate
query restore_zero() as unattached branch on "${c04}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c05

--- mutate
query set_one() as unattached branch on "${c05}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c06

--- mutate
query restore_zero() as unattached branch on "${c06}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c07

--- mutate
query set_one() as unattached branch on "${c07}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c08

--- mutate
query restore_zero() as unattached branch on "${c08}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c09

--- mutate
query set_one() as unattached branch on "${c09}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c10

--- mutate
query restore_zero() as unattached branch on "${c10}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c11

--- mutate
query set_one() as unattached branch on "${c11}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c12

--- mutate
query restore_zero() as unattached branch on "${c12}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c13

--- mutate
query set_one() as unattached branch on "${c13}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c14

--- mutate
query restore_zero() as unattached branch on "${c14}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c15

--- mutate
query set_one() as unattached branch on "${c15}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c16

--- mutate
query restore_zero() as unattached branch on "${c16}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c17

--- mutate
query set_one() as unattached branch on "${c17}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c18

--- mutate
query restore_zero() as unattached branch on "${c18}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c19

--- mutate
query set_one() as unattached branch on "${c19}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c20

--- mutate
query restore_zero() as unattached branch on "${c20}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c21

--- mutate
query set_one() as unattached branch on "${c21}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c22

--- mutate
query restore_zero() as unattached branch on "${c22}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c23

--- mutate
query set_one() as unattached branch on "${c23}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c24

--- mutate
query restore_zero() as unattached branch on "${c24}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c25

--- mutate
query set_one() as unattached branch on "${c25}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c26

--- mutate
query restore_zero() as unattached branch on "${c26}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c27

--- mutate
query set_one() as unattached branch on "${c27}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c28

--- mutate
query restore_zero() as unattached branch on "${c28}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c29

--- mutate
query set_one() as unattached branch on "${c29}" { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c30

--- mutate
query restore_zero() as unattached branch on "${c30}" { update HistoryRow set { value: 0 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $c31

--- query snapshot: $c31
query current_rows() { match { $r: HistoryRow } return { $r.key as key, $r.value as value, $r.payload as payload } }
--- expect unordered
{"key":"hot","value":0,"payload":"fixed"}
--- expect shape
key: String
value: I64
payload: String

--- query branch: main
query current_rows() { match { $r: HistoryRow } return { $r.key as key, $r.value as value, $r.payload as payload } }
--- expect unordered
{"key":"hot","value":0,"payload":"fixed"}
--- expect shape
key: String
value: I64
payload: String
44 changes: 44 additions & 0 deletions benchmarks/workloads/tiny_mutate_unattached.gqt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# issue: none
# notes: The tiny insert as an unattached branch root (`as unattached branch`): the new row is read at
# notes: the snapshot, `main` is read to show its head did not move, and the snapshot is dropped for cleanup.
# notes: Each repetition restores the fixture in a fresh worker.

--- runner
timeout_ms: 600000
environments:
- target: omnigraph-engine
storage: local-filesystem

--- mutate
query add() as unattached branch { insert Item { key: "c", val: 3 } }
--- expect affected: nodes=1 edges=0
--- bind commit $m

--- query snapshot: $m
query items_at_snapshot() {
match { $i: Item }
return { $i.key as key, $i.val as val }
}
--- expect unordered
{"key":"a","val":1}
{"key":"b","val":2}
{"key":"c","val":3}
--- expect shape
key: String
val: I64

--- query branch: main
query items_on_main() {
match { $i: Item }
return { $i.key as key, $i.val as val }
}
--- expect unordered
{"key":"a","val":1}
{"key":"b","val":2}
--- expect shape
key: String
val: I64

--- mutate
commit drop "${m}"
--- expect ok
48 changes: 48 additions & 0 deletions benchmarks/workloads/very_long_history_write_unattached.gqt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# issue: none
# notes: The history checkpoint's next write as an unattached branch root: the updated row is read at
# notes: the snapshot before and after a restart, `main` keeps the fixture's value, and the snapshot
# notes: is dropped. The selected write is separate from verification.

--- runner
timeout_ms: 60000
environments:
- target: omnigraph-engine
storage: local-filesystem

--- mutate
query next_write() as unattached branch { update HistoryRow set { value: 1 } where key = "hot" }
--- expect affected: nodes=1 edges=0
--- bind commit $m

--- query snapshot: $m
query snapshot_rows() { match { $r: HistoryRow } return { $r.key as key, $r.value as value, $r.payload as payload } }
--- expect unordered
{"key":"hot","value":1,"payload":"fixed"}
--- expect shape
key: String
value: I64
payload: String

--- query branch: main
query current_rows() { match { $r: HistoryRow } return { $r.key as key, $r.value as value, $r.payload as payload } }
--- expect unordered
{"key":"hot","value":0,"payload":"fixed"}
--- expect shape
key: String
value: I64
payload: String

--- restart

--- query snapshot: $m
query snapshot_rows_after_restart() { match { $r: HistoryRow } return { $r.key as key, $r.value as value, $r.payload as payload } }
--- expect unordered
{"key":"hot","value":1,"payload":"fixed"}
--- expect shape
key: String
value: I64
payload: String

--- mutate
commit drop "${m}"
--- expect ok
1 change: 1 addition & 0 deletions changelog.d/unattached-branch-benchmarks.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- The benchmark catalog measures a write as an unattached branch root beside its named-branch twin: `tiny-mutate-unattached` (the tiny insert), `very-long-history-32-write-unattached` (the next update on 32 published updates) and `unattached-chain-32-write` (the next root beside a retained 32-snapshot chain), each verified at its snapshot, with `main` unchanged, and dropped. These records cost the root write only; a chained child is not a selectable step, and per-phase attribution stays merge-only.
Loading
Loading