beamdb 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,6 +23,7 @@
23
23
  - [Wire Protocol](#wire-protocol)
24
24
  - [Configuration](#configuration)
25
25
  - [Testing](#testing)
26
+ - [Benchmarks](#benchmarks)
26
27
  - [Features](#features)
27
28
  - [Security](#security)
28
29
  - [Contributing](#contributing)
@@ -803,6 +804,7 @@ let config = Config {
803
804
  my_pub: Some("x.y".into()),
804
805
  broadcast_buffer_size: 4096,
805
806
  ice_servers: vec!["stun:stun.l.google.com:19302".into()],
807
+ dedup_capacity: 100_000,
806
808
  };
807
809
  # }
808
810
  ```
@@ -876,7 +878,6 @@ cargo clippy -- -D warnings
876
878
  # Doctests only (verifies README code examples compile)
877
879
  cargo test --doc
878
880
 
879
- # Benchmarks
880
881
  cargo bench
881
882
 
882
883
  # Run a specific integration test
@@ -907,6 +908,114 @@ cargo test --test wire_live -- --ignored # Layer 3: live integration (needs Nod
907
908
 
908
909
  ---
909
910
 
911
+ ## Benchmarks
912
+
913
+ BEAM includes a comprehensive benchmarking suite covering relay throughput,
914
+ micro-benchmarks for hot-path components, and storage performance.
915
+
916
+ ### Local Put Throughput
917
+
918
+ Local (non-relay) puts through the actor pipeline — measures the full
919
+ `Node::handle → Router::route → MemoryStorage::apply` path with no network I/O:
920
+
921
+ | Scenario | Messages | Throughput |
922
+ |----------|----------|------------|
923
+ | 1 sender × 10k | 10,000 | ~24,000–53,000 puts/sec |
924
+
925
+ Throughput varies with system load. On a dedicated machine with no
926
+ competing processes, expect 50,000+ puts/sec. The bottleneck is
927
+ `Value` cloning for broadcast channels — further gains require
928
+ `Arc<Value>` to make cloning a refcount bump.
929
+
930
+ ### Relay Throughput
931
+
932
+ Real WebSocket connections through a memory-only relay (no disk I/O):
933
+
934
+ | Scenario | Messages | Throughput |
935
+ |----------|----------|------------|
936
+ | 1 sender × 10k | 10,000 | ~5,300 msgs/sec |
937
+ | 1 sender × 50k | 50,000 | ~10,600 msgs/sec |
938
+ | 10 senders × 5k | 50,000 | ~11,400 msgs/sec |
939
+
940
+ The relay's internal processing (parse + dedup + route + serialize) runs in
941
+ microseconds — the bottleneck is client-side `put().await`, not the relay.
942
+
943
+ ### Micro-Benchmarks (Criterion)
944
+
945
+ | Operation | Time |
946
+ |-----------|------|
947
+ | Parse small Put JSON | 1,067 ns |
948
+ | Parse medium Put JSON | 2.00 µs |
949
+ | Serialize small Put JSON | 69 ns |
950
+ | Parse Get | 677 ns |
951
+ | Dedup check (fresh) | 274 µs |
952
+ | Dedup check (duplicate) | 41.8 µs |
953
+ | Actor mailbox send+recv | 309 µs |
954
+
955
+ ### WASM Benchmarks (Node.js)
956
+
957
+ | Operation | WASM | Native | Ratio |
958
+ |-----------|------|--------|-------|
959
+ | Parse small Put | 7.9 µs | 1,067 ns | ~7.4× |
960
+ | Serialize small Put | 8.6 µs | 69 ns | ~125× |
961
+ | Parse Get | 4.5 µs | 677 ns | ~6.7× |
962
+
963
+ Run with: `wasm-pack test --node --no-default-features -- --nocapture`
964
+
965
+ ### WASM Relay Throughput (Browser-only)
966
+
967
+ `web_sys::WebSocket` callbacks don't fire in Node.js `wasm-bindgen-test-runner`
968
+ ([known limitation](https://github.com/wasm-bindgen/wasm-bindgen/issues/4921)).
969
+ Use the browser benchmark page to measure WASM relay throughput:
970
+
971
+ ```bash
972
+ cargo run -- start --port 4944 --memory-storage true --redb-storage false
973
+ python3 -m http.server 8080 -d examples/
974
+ # Open http://localhost:8080/bench.html in a browser
975
+ ```
976
+
977
+ Previous v0.11.0 browser results: ~115–651 msgs/sec depending on batch size.
978
+
979
+ ### Browser Benchmark
980
+
981
+ An interactive benchmark page is available at `examples/bench.html`:
982
+
983
+ ```bash
984
+ # Start a relay
985
+ cargo run -- start --port 4944 --memory-storage true --redb-storage false
986
+
987
+ # Serve the benchmark page
988
+ python3 -m http.server 8080 -d examples/
989
+
990
+ # Open in browser
991
+ open http://localhost:8080/bench.html
992
+ ```
993
+
994
+ The browser benchmark measures:
995
+ - **Relay TPS**: end-to-end throughput through a real relay
996
+ - **Put throughput**: local WASM API fire-and-forget puts
997
+ - **Get throughput**: local WASM API promise resolution
998
+ - **Put→Get round-trip**: full local cycle
999
+
1000
+ ### Running Benchmarks
1001
+
1002
+ ```bash
1003
+ # Relay throughput (release mode required)
1004
+ cargo test --release --test relay_throughput_bench -- --ignored --nocapture
1005
+
1006
+ # Micro-benchmarks (hot-path components)
1007
+ cargo bench --bench my_benchmark -- "wire_|dup_check|actor_mailbox"
1008
+
1009
+ # Storage benchmarks
1010
+ cargo bench --bench my_benchmark -- "write_storm|read_storm|mixed"
1011
+
1012
+ # Live metrics endpoint (while relay is running)
1013
+ curl http://localhost:8080/metrics
1014
+ ```
1015
+
1016
+ See [`benches/RESULTS.md`](benches/RESULTS.md) for full results with
1017
+ methodology and analysis.
1018
+
910
1019
  ## Features
911
1020
 
912
1021
  | Feature | Default | Enables |
package/beam.d.ts CHANGED
@@ -115,11 +115,11 @@ export interface InitOutput {
115
115
  readonly beam_put_num: (a: number, b: number, c: number, d: number) => void;
116
116
  readonly beam_stop: (a: number) => void;
117
117
  readonly task_worker_entry_point: (a: number, b: number) => void;
118
- readonly __wasm_bindgen_func_elem_1101: (a: number, b: number, c: number, d: number) => void;
119
- readonly __wasm_bindgen_func_elem_1115: (a: number, b: number, c: number, d: number) => void;
120
- readonly __wasm_bindgen_func_elem_234: (a: number, b: number, c: number) => void;
121
- readonly __wasm_bindgen_func_elem_234_2: (a: number, b: number, c: number) => void;
122
- readonly __wasm_bindgen_func_elem_234_3: (a: number, b: number, c: number) => void;
118
+ readonly __wasm_bindgen_func_elem_1109: (a: number, b: number, c: number, d: number) => void;
119
+ readonly __wasm_bindgen_func_elem_1123: (a: number, b: number, c: number, d: number) => void;
120
+ readonly __wasm_bindgen_func_elem_232: (a: number, b: number, c: number) => void;
121
+ readonly __wasm_bindgen_func_elem_232_2: (a: number, b: number, c: number) => void;
122
+ readonly __wasm_bindgen_func_elem_232_3: (a: number, b: number, c: number) => void;
123
123
  readonly __wbindgen_export: (a: number, b: number) => number;
124
124
  readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
125
125
  readonly __wbindgen_export3: (a: number) => void;
package/beam.js CHANGED
@@ -290,7 +290,7 @@ function __wbg_get_imports() {
290
290
  const a = state0.a;
291
291
  state0.a = 0;
292
292
  try {
293
- return __wasm_bindgen_func_elem_1115(a, state0.b, arg0, arg1);
293
+ return __wasm_bindgen_func_elem_1123(a, state0.b, arg0, arg1);
294
294
  } finally {
295
295
  state0.a = a;
296
296
  }
@@ -308,7 +308,7 @@ function __wbg_get_imports() {
308
308
  const a = state0.a;
309
309
  state0.a = 0;
310
310
  try {
311
- return __wasm_bindgen_func_elem_1115(a, state0.b, arg0, arg1);
311
+ return __wasm_bindgen_func_elem_1123(a, state0.b, arg0, arg1);
312
312
  } finally {
313
313
  state0.a = a;
314
314
  }
@@ -432,23 +432,23 @@ function __wbg_get_imports() {
432
432
  return addHeapObject(ret);
433
433
  }, arguments); },
434
434
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
435
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 12, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
436
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_234);
435
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 15, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
436
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_232);
437
437
  return addHeapObject(ret);
438
438
  },
439
439
  __wbindgen_cast_0000000000000002: function(arg0, arg1) {
440
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 269, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
441
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_1101);
440
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 272, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
441
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_1109);
442
442
  return addHeapObject(ret);
443
443
  },
444
444
  __wbindgen_cast_0000000000000003: function(arg0, arg1) {
445
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("IDBVersionChangeEvent")], shim_idx: 12, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
446
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_234_2);
445
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("IDBVersionChangeEvent")], shim_idx: 15, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
446
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_232_2);
447
447
  return addHeapObject(ret);
448
448
  },
449
449
  __wbindgen_cast_0000000000000004: function(arg0, arg1) {
450
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("MessageEvent")], shim_idx: 12, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
451
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_234_3);
450
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("MessageEvent")], shim_idx: 15, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
451
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_232_3);
452
452
  return addHeapObject(ret);
453
453
  },
454
454
  __wbindgen_cast_0000000000000005: function(arg0) {
@@ -475,22 +475,22 @@ function __wbg_get_imports() {
475
475
  };
476
476
  }
477
477
 
478
- function __wasm_bindgen_func_elem_234(arg0, arg1, arg2) {
479
- wasm.__wasm_bindgen_func_elem_234(arg0, arg1, addHeapObject(arg2));
478
+ function __wasm_bindgen_func_elem_232(arg0, arg1, arg2) {
479
+ wasm.__wasm_bindgen_func_elem_232(arg0, arg1, addHeapObject(arg2));
480
480
  }
481
481
 
482
- function __wasm_bindgen_func_elem_234_2(arg0, arg1, arg2) {
483
- wasm.__wasm_bindgen_func_elem_234_2(arg0, arg1, addHeapObject(arg2));
482
+ function __wasm_bindgen_func_elem_232_2(arg0, arg1, arg2) {
483
+ wasm.__wasm_bindgen_func_elem_232_2(arg0, arg1, addHeapObject(arg2));
484
484
  }
485
485
 
486
- function __wasm_bindgen_func_elem_234_3(arg0, arg1, arg2) {
487
- wasm.__wasm_bindgen_func_elem_234_3(arg0, arg1, addHeapObject(arg2));
486
+ function __wasm_bindgen_func_elem_232_3(arg0, arg1, arg2) {
487
+ wasm.__wasm_bindgen_func_elem_232_3(arg0, arg1, addHeapObject(arg2));
488
488
  }
489
489
 
490
- function __wasm_bindgen_func_elem_1101(arg0, arg1, arg2) {
490
+ function __wasm_bindgen_func_elem_1109(arg0, arg1, arg2) {
491
491
  try {
492
492
  const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
493
- wasm.__wasm_bindgen_func_elem_1101(retptr, arg0, arg1, addHeapObject(arg2));
493
+ wasm.__wasm_bindgen_func_elem_1109(retptr, arg0, arg1, addHeapObject(arg2));
494
494
  var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
495
495
  var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
496
496
  if (r1) {
@@ -501,8 +501,8 @@ function __wasm_bindgen_func_elem_1101(arg0, arg1, arg2) {
501
501
  }
502
502
  }
503
503
 
504
- function __wasm_bindgen_func_elem_1115(arg0, arg1, arg2, arg3) {
505
- wasm.__wasm_bindgen_func_elem_1115(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
504
+ function __wasm_bindgen_func_elem_1123(arg0, arg1, arg2, arg3) {
505
+ wasm.__wasm_bindgen_func_elem_1123(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
506
506
  }
507
507
 
508
508
 
package/beam_bg.wasm CHANGED
Binary file
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "David Newman <david.r.newman@proton.me>"
7
7
  ],
8
8
  "description": "BEAM — distributed graph database syncing over WebSocket, WebRTC, and multicast. Successor to rod.",
9
- "version": "0.10.0",
9
+ "version": "0.12.0",
10
10
  "license": "MIT",
11
11
  "repository": {
12
12
  "type": "git",