Skip to content

Add backup/restore tests for Memory and ScyllaDB backends (Phase 0b)#6392

Draft
ndr-ds wants to merge 4 commits into
mainfrom
ndr-ds/phase-0b-memory-scylla-backup-tests
Draft

Add backup/restore tests for Memory and ScyllaDB backends (Phase 0b)#6392
ndr-ds wants to merge 4 commits into
mainfrom
ndr-ds/phase-0b-memory-scylla-backup-tests

Conversation

@ndr-ds

@ndr-ds ndr-ds commented May 26, 2026

Copy link
Copy Markdown
Contributor

Motivation

Phase 0a (#6332) verified that a WorkerState can boot from a RocksDB backup produced by a different validator. This follow-up extends the DatabaseBackup trait and cross-key boot tests to the MemoryDatabase and ScyllaDbDatabase backends.

Proposal

linera-views changes:

  • DatabaseBackup for MemoryDatabase: BCS-serializes all root-key partitions to memory_backup.bcs (BTreeMap<root_key, BTreeMap<k, v>>).
  • DatabaseBackup for ScyllaDbDatabaseInternal: full-table SELECT root_key, k, v scan written to scylladb_backup.bcs in the same format. Uses a fresh thread + current_thread Tokio runtime to bridge the sync trait into async CQL without nesting runtimes.
  • DatabaseBackup forwarding impl for JournalingKeyValueDatabase<D> — fills the missing link in the ScyllaDB wrapper chain (LruCachingDatabase → ValueSplittingDatabase → JournalingKeyValueDatabase → ScyllaDbDatabaseInternal).
  • DatabaseBackup doc comment updated to be backend-agnostic.

linera-core changes:

  • Backup test module now compiled under #[cfg(test)] (was rocksdb-only), with per-backend #[cfg(feature = "...")] guards inside the file.
  • 9 tests total — 3 scenarios × 3 backends (memory, rocksdb, scylladb): no-key observer, mismatched-key, stale-backup-with-own-key.
  • Memory restore: deserializes the BCS dump, creates a fresh namespace, replays writes via open_shared + write_batch.
  • ScyllaDB restore: same BCS format; strips the get_big_root_key leading byte to recover the logical root key, re-inserts via ScyllaDbDatabaseInternal::open_shared + write_batch.

Test Plan

  • Memory tests (3): cargo test --package linera-core --features test worker_backup_testspass.
  • RocksDB tests (3): cargo test --package linera-core --features test,rocksdb worker_backup_testspass.
  • ScyllaDB tests (3): compile-checked locally; exercised by the scylladb.yml CI workflow (Docker scylladb/scylla:6.1).
  • cargo clippy clean on all three feature combinations (test, test,rocksdb, test,rocksdb,scylladb).

Release Plan

  • Nothing to do / These changes follow the usual release cycle.

Links

@github-actions

github-actions Bot commented May 26, 2026

Copy link
Copy Markdown

Instruction Count Benchmark Results

Baseline: 689ac730c7

Deterministic metrics — reproducible across runs (34 benchmarks)
Benchmark Instructions Total R+W
BucketQueueView
delete_500_from_1000 19,252 (-0.20%) 28,667 (-0.16%)
front_100_from_1000 5,599 (-0.34%) 8,281 (-0.29%)
pre_save_1000 41,837 (-0.05%) 58,671 (-0.04%)
push_1000 23,046 (+0.08%) 31,874 (+0.08%)
Cold Load
load_1000 690,687 (No change) 1,006,158 (No change)
CollectionView
indices_100 190,924 (-0.01%) 265,291 (-0.01%)
load_all_100_from_storage 618,662 (No change) 873,273 (No change)
load_all_100_in_memory 340,856 (No change) 477,890 (No change)
pre_save_100 258,786 (No change) 357,810 (No change)
try_load_10_from_100 101,154 (-0.02%) 142,940 (-0.02%)
MapView
contains_key_10_from_100 52,082 (No change) 73,463 (No change)
contains_key_10_from_1000 351,805 (+0.01%) 497,010 (+0.00%)
get_10_from_100 54,667 (+0.47%) 77,326 (+0.46%)
get_10_from_1000 354,381 (No change) 500,869 (No change)
get_100_missing_from_1000 599,266 (-0.00%) 832,117 (-0.00%)
indices_100 99,886 (No change) 137,775 (No change)
indices_1000 944,598 (No change) 1,319,365 (No change)
insert_100 254,653 (No change) 347,556 (No change)
insert_1000 2,922,787 (No change) 3,915,120 (No change)
post_save_1000 1,020,741 (No change) 1,472,744 (No change)
pre_save_100 322,045 (+0.01%) 447,691 (+0.01%)
pre_save_1000 3,277,197 (No change) 4,612,212 (No change)
remove_500_from_1000 1,191,889 (No change) 1,643,783 (No change)
QueueView
delete_500_from_1000 11,157 (No change) 13,231 (No change)
front_100_from_1000 7,837 (No change) 12,041 (No change)
pre_save_1000 1,114,522 (No change) 1,588,028 (No change)
push_1000 22,971 (No change) 31,773 (No change)
ReentrantCollectionView
contains_key_10_from_100 142,427 (No change) 202,240 (No change)
indices_100 235,812 (No change) 330,225 (No change)
load_all_100_from_storage 777,847 (No change) 1,097,423 (No change)
load_all_100_in_memory 415,420 (No change) 573,683 (No change)
pre_save_100 342,957 (No change) 477,434 (No change)
RegisterView
get_set_100 83,830 (No change) 118,850 (No change)
pre_save 5,411 (-0.35%) 7,981 (-0.30%)

Regression threshold: 1%${\color{red}\textbf{red}}$ = regression, ${\color{green}\textbf{green}}$ = improvement.

Cache-dependent metrics — expect fluctuations between runs (34 benchmarks)
Benchmark L1 Hits LLC Hits RAM Hits Est. Cycles
BucketQueueView
delete_500_from_1000 28,480 (-0.18%) 31 (${\color{red}\textbf{+10.71\%%}}$) 156 (No change) 34,095 (-0.10%)
front_100_from_1000 8,121 (-0.25%) 33 (${\color{green}\textbf{-8.33\%%}}$) 127 (-0.78%) 12,731 (-0.55%)
pre_save_1000 58,210 (-0.03%) 81 (${\color{green}\textbf{-8.99\%%}}$) 380 (-0.26%) 71,915 (-0.12%)
push_1000 31,671 (+0.07%) 51 (No change) 152 (+0.66%) 37,246 (+0.16%)
Cold Load
load_1000 997,625 (+0.00%) 8,363 (-0.02%) 170 (No change) 1,045,390 (-0.00%)
CollectionView
indices_100 264,034 (-0.01%) 870 (-0.80%) 387 (-0.26%) 281,929 (-0.03%)
load_all_100_from_storage 868,737 (-0.00%) 3,877 (+0.10%) 659 (No change) 911,187 (+0.00%)
load_all_100_in_memory 475,758 (+0.00%) 1,388 (-0.14%) 744 (No change) 508,738 (-0.00%)
pre_save_100 355,876 (No change) 1,345 (No change) 589 (No change) 383,216 (No change)
try_load_10_from_100 142,075 (-0.01%) 638 (-0.93%) 227 (-0.44%) 153,210 (-0.05%)
MapView
contains_key_10_from_100 73,186 (-0.00%) 82 (${\color{red}\textbf{+2.50\%%}}$) 195 (No change) 80,421 (+0.01%)
contains_key_10_from_1000 493,840 (+0.00%) 2,975 (+0.10%) 195 (+0.52%) 515,540 (+0.01%)
get_10_from_100 77,030 (+0.45%) 92 (${\color{red}\textbf{+6.98\%%}}$) 204 (${\color{red}\textbf{+3.03\%%}}$) 84,630 (+0.69%)
get_10_from_1000 497,684 (+0.00%) 2,981 (-0.03%) 204 (No change) 519,729 (-0.00%)
get_100_missing_from_1000 828,917 (-0.00%) 2,980 (-0.17%) 220 (-0.45%) 851,517 (-0.01%)
indices_100 137,136 (+0.00%) 245 (${\color{green}\textbf{-1.21\%%}}$) 394 (No change) 152,151 (-0.01%)
indices_1000 1,311,716 (No change) 6,471 (No change) 1,178 (No change) 1,385,301 (No change)
insert_100 346,826 (-0.00%) 96 (${\color{red}\textbf{+1.05\%%}}$) 634 (No change) 369,496 (+0.00%)
insert_1000 3,908,087 (-0.00%) 3,068 (+0.92%) 3,965 (No change) 4,062,202 (+0.00%)
post_save_1000 1,461,355 (-0.00%) 11,216 (+0.02%) 173 (No change) 1,523,490 (+0.00%)
pre_save_100 446,327 (+0.00%) 762 (+0.66%) 602 (+0.17%) 471,207 (+0.02%)
pre_save_1000 4,598,311 (+0.00%) 10,097 (-0.01%) 3,804 (No change) 4,781,936 (-0.00%)
remove_500_from_1000 1,639,402 (-0.00%) 4,212 (+0.02%) 169 (No change) 1,666,377 (+0.00%)
QueueView
delete_500_from_1000 13,064 (-0.02%) 36 (${\color{red}\textbf{+5.88\%%}}$) 131 (No change) 17,829 (+0.04%)
front_100_from_1000 11,851 (+0.01%) 35 (${\color{green}\textbf{-2.78\%%}}$) 155 (No change) 17,451 (-0.02%)
pre_save_1000 1,583,320 (No change) 2,756 (No change) 1,952 (No change) 1,665,420 (No change)
push_1000 31,570 (-0.01%) 51 (${\color{red}\textbf{+4.08\%%}}$) 152 (No change) 37,145 (+0.02%)
ReentrantCollectionView
contains_key_10_from_100 201,007 (+0.00%) 1,031 (-0.10%) 202 (No change) 213,232 (-0.00%)
indices_100 328,665 (No change) 1,196 (No change) 364 (No change) 347,385 (No change)
load_all_100_from_storage 1,090,336 (-0.00%) 6,695 (+0.01%) 392 (No change) 1,137,531 (+0.00%)
load_all_100_in_memory 571,564 (-0.00%) 1,586 (+0.06%) 533 (No change) 598,149 (+0.00%)
pre_save_100 474,373 (-0.00%) 2,378 (+0.04%) 683 (No change) 510,168 (+0.00%)
RegisterView
get_set_100 118,638 (No change) 38 (No change) 174 (No change) 124,918 (No change)
pre_save 7,794 (-0.15%) 32 (${\color{green}\textbf{-25.58\%%}}$) 155 (-0.64%) 13,379 (-0.76%)

Cache metrics fluctuate because anything that changes the virtual memory layout
shifts which data lands on which cache lines, changing the L1/LLC/RAM distribution.
Probable causes: ASLR (even across identical binaries), executable binary size changes,
shared library size changes, and even filename length differences.

Cachegrind simulates a two-level cache (L1 + LLC) auto-detected from the host CPU.
Est. Cycles = L1 hits + 5 × LLC hits + 35 × RAM hits.

Runner cache sizes: L1d cache: 64 KiB (2 instances);L1i cache: 64 KiB (2 instances) L2 cache: 1 MiB (2 instances);L3 cache: 32 MiB (1 instance)

ndr-ds added 3 commits May 29, 2026 16:14
Extends the DatabaseBackup trait and cross-key boot tests introduced in
#6332 to cover MemoryDatabase and ScyllaDbDatabase in addition to RocksDB.

linera-views:
- MemoryDatabase: backup serializes all root-key partitions to
  memory_backup.bcs (BCS-encoded BTreeMap<root_key, BTreeMap<k, v>>).
- ScyllaDbDatabaseInternal: full-table SELECT scan written to
  scylladb_backup.bcs in the same format; uses a fresh thread +
  current_thread Tokio runtime to bridge the sync trait into async CQL.
- JournalingKeyValueDatabase<D>: added DatabaseBackup forwarding impl to
  complete the ScyllaDB wrapper chain.
- DatabaseBackup doc comment updated to be backend-agnostic.

linera-core:
- Backup test module now compiled under #[cfg(test)] (was rocksdb-only),
  with per-backend #[cfg(feature)] guards inside the file.
- 9 tests total: 3 scenarios x 3 backends (memory, rocksdb, scylladb).
- Memory restore: BCS deserialize + open_shared + write_batch.
- ScyllaDB restore: same BCS format, strips get_big_root_key prefix byte,
  re-inserts via ScyllaDbDatabaseInternal::open_shared + write_batch.
@ndr-ds ndr-ds force-pushed the ndr-ds/phase-0b-memory-scylla-backup-tests branch from f129f15 to 103df17 Compare May 29, 2026 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant