@lix-js/sdk 0.6.0-preview.4 → 0.6.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 +76 -4
- package/dist/errors.d.ts +7 -0
- package/dist/errors.js +19 -0
- package/dist/index.d.ts +4 -5
- package/dist/index.js +3 -3
- package/dist/native.d.ts +1 -0
- package/dist/native.js +47 -0
- package/dist/open-lix.d.ts +39 -201
- package/dist/open-lix.js +59 -284
- package/dist/result.d.ts +18 -0
- package/dist/result.js +48 -0
- package/dist/types.d.ts +114 -1
- package/dist/value.d.ts +28 -0
- package/dist/value.js +245 -0
- package/package.json +20 -50
- package/SKILL.md +0 -506
- package/dist/builtin-schemas.d.ts +0 -1
- package/dist/builtin-schemas.js +0 -1
- package/dist/engine-wasm/index.d.ts +0 -87
- package/dist/engine-wasm/index.js +0 -339
- package/dist/engine-wasm/wasm/lix_engine.d.ts +0 -79
- package/dist/engine-wasm/wasm/lix_engine.js +0 -821
- package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
- package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +0 -26
- package/dist/generated/builtin-schemas.d.ts +0 -427
- package/dist/generated/builtin-schemas.js +0 -643
- package/dist/sqlite/index.d.ts +0 -12
- package/dist/sqlite/index.js +0 -303
- package/dist-engine-src/README.md +0 -18
- package/dist-engine-src/src/backend/kv.rs +0 -358
- package/dist-engine-src/src/backend/mod.rs +0 -12
- package/dist-engine-src/src/backend/testing.rs +0 -658
- package/dist-engine-src/src/backend/types.rs +0 -96
- package/dist-engine-src/src/binary_cas/chunking.rs +0 -31
- package/dist-engine-src/src/binary_cas/codec.rs +0 -346
- package/dist-engine-src/src/binary_cas/context.rs +0 -139
- package/dist-engine-src/src/binary_cas/kv.rs +0 -1063
- package/dist-engine-src/src/binary_cas/mod.rs +0 -11
- package/dist-engine-src/src/binary_cas/types.rs +0 -121
- package/dist-engine-src/src/catalog/context.rs +0 -412
- package/dist-engine-src/src/catalog/mod.rs +0 -10
- package/dist-engine-src/src/catalog/schema.rs +0 -4
- package/dist-engine-src/src/catalog/snapshot.rs +0 -1114
- package/dist-engine-src/src/cel/context.rs +0 -86
- package/dist-engine-src/src/cel/error.rs +0 -19
- package/dist-engine-src/src/cel/mod.rs +0 -8
- package/dist-engine-src/src/cel/provider.rs +0 -9
- package/dist-engine-src/src/cel/runtime.rs +0 -167
- package/dist-engine-src/src/cel/value.rs +0 -50
- package/dist-engine-src/src/commit_graph/context.rs +0 -901
- package/dist-engine-src/src/commit_graph/mod.rs +0 -11
- package/dist-engine-src/src/commit_graph/types.rs +0 -109
- package/dist-engine-src/src/commit_graph/walker.rs +0 -756
- package/dist-engine-src/src/commit_store/codec.rs +0 -887
- package/dist-engine-src/src/commit_store/context.rs +0 -944
- package/dist-engine-src/src/commit_store/materialization.rs +0 -84
- package/dist-engine-src/src/commit_store/mod.rs +0 -16
- package/dist-engine-src/src/commit_store/storage.rs +0 -600
- package/dist-engine-src/src/commit_store/types.rs +0 -215
- package/dist-engine-src/src/common/error.rs +0 -313
- package/dist-engine-src/src/common/fingerprint.rs +0 -3
- package/dist-engine-src/src/common/fs_path.rs +0 -1336
- package/dist-engine-src/src/common/identity.rs +0 -145
- package/dist-engine-src/src/common/json_pointer.rs +0 -67
- package/dist-engine-src/src/common/metadata.rs +0 -40
- package/dist-engine-src/src/common/mod.rs +0 -23
- package/dist-engine-src/src/common/types.rs +0 -105
- package/dist-engine-src/src/common/wire.rs +0 -222
- package/dist-engine-src/src/domain.rs +0 -324
- package/dist-engine-src/src/engine.rs +0 -225
- package/dist-engine-src/src/entity_identity.rs +0 -405
- package/dist-engine-src/src/functions/context.rs +0 -292
- package/dist-engine-src/src/functions/deterministic.rs +0 -113
- package/dist-engine-src/src/functions/mod.rs +0 -18
- package/dist-engine-src/src/functions/provider.rs +0 -130
- package/dist-engine-src/src/functions/state.rs +0 -336
- package/dist-engine-src/src/functions/types.rs +0 -37
- package/dist-engine-src/src/init.rs +0 -558
- package/dist-engine-src/src/json_store/compression.rs +0 -77
- package/dist-engine-src/src/json_store/context.rs +0 -423
- package/dist-engine-src/src/json_store/encoded.rs +0 -15
- package/dist-engine-src/src/json_store/mod.rs +0 -12
- package/dist-engine-src/src/json_store/store.rs +0 -1109
- package/dist-engine-src/src/json_store/types.rs +0 -217
- package/dist-engine-src/src/lib.rs +0 -62
- package/dist-engine-src/src/live_state/context.rs +0 -2019
- package/dist-engine-src/src/live_state/mod.rs +0 -15
- package/dist-engine-src/src/live_state/overlay.rs +0 -75
- package/dist-engine-src/src/live_state/reader.rs +0 -23
- package/dist-engine-src/src/live_state/types.rs +0 -222
- package/dist-engine-src/src/live_state/visibility.rs +0 -223
- package/dist-engine-src/src/plugin/archive.rs +0 -438
- package/dist-engine-src/src/plugin/component.rs +0 -183
- package/dist-engine-src/src/plugin/install.rs +0 -619
- package/dist-engine-src/src/plugin/manifest.rs +0 -516
- package/dist-engine-src/src/plugin/materializer.rs +0 -477
- package/dist-engine-src/src/plugin/mod.rs +0 -33
- package/dist-engine-src/src/plugin/plugin_manifest.json +0 -118
- package/dist-engine-src/src/plugin/storage.rs +0 -74
- package/dist-engine-src/src/schema/annotations/defaults.rs +0 -275
- package/dist-engine-src/src/schema/annotations/mod.rs +0 -1
- package/dist-engine-src/src/schema/builtin/lix_account.json +0 -21
- package/dist-engine-src/src/schema/builtin/lix_active_account.json +0 -29
- package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +0 -29
- package/dist-engine-src/src/schema/builtin/lix_change.json +0 -63
- package/dist-engine-src/src/schema/builtin/lix_change_author.json +0 -45
- package/dist-engine-src/src/schema/builtin/lix_commit.json +0 -24
- package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +0 -53
- package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +0 -52
- package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +0 -52
- package/dist-engine-src/src/schema/builtin/lix_key_value.json +0 -40
- package/dist-engine-src/src/schema/builtin/lix_label.json +0 -29
- package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +0 -74
- package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +0 -25
- package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -34
- package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -48
- package/dist-engine-src/src/schema/builtin/mod.rs +0 -222
- package/dist-engine-src/src/schema/compatibility.rs +0 -787
- package/dist-engine-src/src/schema/definition.json +0 -187
- package/dist-engine-src/src/schema/definition.rs +0 -742
- package/dist-engine-src/src/schema/key.rs +0 -138
- package/dist-engine-src/src/schema/mod.rs +0 -20
- package/dist-engine-src/src/schema/seed.rs +0 -14
- package/dist-engine-src/src/schema/tests.rs +0 -780
- package/dist-engine-src/src/session/context.rs +0 -404
- package/dist-engine-src/src/session/create_version.rs +0 -88
- package/dist-engine-src/src/session/execute.rs +0 -541
- package/dist-engine-src/src/session/merge/analysis.rs +0 -102
- package/dist-engine-src/src/session/merge/apply.rs +0 -23
- package/dist-engine-src/src/session/merge/conflicts.rs +0 -63
- package/dist-engine-src/src/session/merge/mod.rs +0 -11
- package/dist-engine-src/src/session/merge/stats.rs +0 -65
- package/dist-engine-src/src/session/merge/version.rs +0 -427
- package/dist-engine-src/src/session/mod.rs +0 -27
- package/dist-engine-src/src/session/optimization9_sql2_bench.rs +0 -100
- package/dist-engine-src/src/session/switch_version.rs +0 -110
- package/dist-engine-src/src/session/transaction.rs +0 -76
- package/dist-engine-src/src/sql2/change_provider.rs +0 -331
- package/dist-engine-src/src/sql2/classify.rs +0 -174
- package/dist-engine-src/src/sql2/context.rs +0 -311
- package/dist-engine-src/src/sql2/directory_history_provider.rs +0 -631
- package/dist-engine-src/src/sql2/directory_provider.rs +0 -2453
- package/dist-engine-src/src/sql2/dml.rs +0 -148
- package/dist-engine-src/src/sql2/entity_history_provider.rs +0 -440
- package/dist-engine-src/src/sql2/entity_provider.rs +0 -3211
- package/dist-engine-src/src/sql2/error.rs +0 -215
- package/dist-engine-src/src/sql2/execute.rs +0 -3533
- package/dist-engine-src/src/sql2/file_history_provider.rs +0 -910
- package/dist-engine-src/src/sql2/file_provider.rs +0 -3679
- package/dist-engine-src/src/sql2/filesystem_planner.rs +0 -1490
- package/dist-engine-src/src/sql2/filesystem_predicates.rs +0 -159
- package/dist-engine-src/src/sql2/filesystem_visibility.rs +0 -383
- package/dist-engine-src/src/sql2/history_projection.rs +0 -56
- package/dist-engine-src/src/sql2/history_provider.rs +0 -412
- package/dist-engine-src/src/sql2/history_route.rs +0 -657
- package/dist-engine-src/src/sql2/lix_state_provider.rs +0 -2512
- package/dist-engine-src/src/sql2/mod.rs +0 -47
- package/dist-engine-src/src/sql2/predicate_typecheck.rs +0 -246
- package/dist-engine-src/src/sql2/public_bind/assignment.rs +0 -46
- package/dist-engine-src/src/sql2/public_bind/capability.rs +0 -41
- package/dist-engine-src/src/sql2/public_bind/dml.rs +0 -172
- package/dist-engine-src/src/sql2/public_bind/mod.rs +0 -26
- package/dist-engine-src/src/sql2/public_bind/table.rs +0 -168
- package/dist-engine-src/src/sql2/read_only.rs +0 -63
- package/dist-engine-src/src/sql2/record_batch.rs +0 -17
- package/dist-engine-src/src/sql2/result_metadata.rs +0 -29
- package/dist-engine-src/src/sql2/runtime.rs +0 -60
- package/dist-engine-src/src/sql2/session.rs +0 -132
- package/dist-engine-src/src/sql2/udfs/common.rs +0 -295
- package/dist-engine-src/src/sql2/udfs/lix_active_version_commit_id.rs +0 -53
- package/dist-engine-src/src/sql2/udfs/lix_empty_blob.rs +0 -47
- package/dist-engine-src/src/sql2/udfs/lix_json.rs +0 -100
- package/dist-engine-src/src/sql2/udfs/lix_json_get.rs +0 -99
- package/dist-engine-src/src/sql2/udfs/lix_json_get_text.rs +0 -99
- package/dist-engine-src/src/sql2/udfs/lix_text_decode.rs +0 -82
- package/dist-engine-src/src/sql2/udfs/lix_text_encode.rs +0 -85
- package/dist-engine-src/src/sql2/udfs/lix_timestamp.rs +0 -76
- package/dist-engine-src/src/sql2/udfs/lix_uuid_v7.rs +0 -76
- package/dist-engine-src/src/sql2/udfs/mod.rs +0 -89
- package/dist-engine-src/src/sql2/udfs/public_call.rs +0 -238
- package/dist-engine-src/src/sql2/version_provider.rs +0 -1202
- package/dist-engine-src/src/sql2/version_scope.rs +0 -394
- package/dist-engine-src/src/sql2/write_normalization.rs +0 -345
- package/dist-engine-src/src/storage/context.rs +0 -356
- package/dist-engine-src/src/storage/mod.rs +0 -14
- package/dist-engine-src/src/storage/read_scope.rs +0 -88
- package/dist-engine-src/src/storage/types.rs +0 -501
- package/dist-engine-src/src/storage_bench.rs +0 -4863
- package/dist-engine-src/src/test_support.rs +0 -228
- package/dist-engine-src/src/tracked_state/by_file_index.rs +0 -98
- package/dist-engine-src/src/tracked_state/codec.rs +0 -2085
- package/dist-engine-src/src/tracked_state/context.rs +0 -1867
- package/dist-engine-src/src/tracked_state/diff.rs +0 -686
- package/dist-engine-src/src/tracked_state/materialization.rs +0 -403
- package/dist-engine-src/src/tracked_state/materializer.rs +0 -488
- package/dist-engine-src/src/tracked_state/merge.rs +0 -492
- package/dist-engine-src/src/tracked_state/mod.rs +0 -32
- package/dist-engine-src/src/tracked_state/storage.rs +0 -375
- package/dist-engine-src/src/tracked_state/tree.rs +0 -3187
- package/dist-engine-src/src/tracked_state/types.rs +0 -231
- package/dist-engine-src/src/transaction/commit.rs +0 -1484
- package/dist-engine-src/src/transaction/context.rs +0 -1548
- package/dist-engine-src/src/transaction/live_state_overlay.rs +0 -35
- package/dist-engine-src/src/transaction/mod.rs +0 -13
- package/dist-engine-src/src/transaction/normalization.rs +0 -890
- package/dist-engine-src/src/transaction/prep.rs +0 -37
- package/dist-engine-src/src/transaction/schema_resolver.rs +0 -149
- package/dist-engine-src/src/transaction/staging.rs +0 -1731
- package/dist-engine-src/src/transaction/types.rs +0 -460
- package/dist-engine-src/src/transaction/validation.rs +0 -5830
- package/dist-engine-src/src/untracked_state/codec.rs +0 -307
- package/dist-engine-src/src/untracked_state/context.rs +0 -98
- package/dist-engine-src/src/untracked_state/materialization.rs +0 -63
- package/dist-engine-src/src/untracked_state/mod.rs +0 -15
- package/dist-engine-src/src/untracked_state/storage.rs +0 -396
- package/dist-engine-src/src/untracked_state/types.rs +0 -146
- package/dist-engine-src/src/version/context.rs +0 -40
- package/dist-engine-src/src/version/lifecycle.rs +0 -221
- package/dist-engine-src/src/version/mod.rs +0 -13
- package/dist-engine-src/src/version/refs.rs +0 -330
- package/dist-engine-src/src/version/stage_rows.rs +0 -67
- package/dist-engine-src/src/version/types.rs +0 -21
- package/dist-engine-src/src/wasm/mod.rs +0 -60
|
@@ -1,4863 +0,0 @@
|
|
|
1
|
-
use crate::binary_cas::{BinaryCasContext, BlobHash, BlobWrite};
|
|
2
|
-
use crate::catalog::CatalogContext;
|
|
3
|
-
use crate::commit_graph::CommitGraphChangeHistoryRequest;
|
|
4
|
-
use crate::commit_store::{
|
|
5
|
-
Change, ChangeScanRequest, CommitDraftRef, CommitStoreContext, MaterializedChange,
|
|
6
|
-
};
|
|
7
|
-
use crate::entity_identity::EntityIdentity;
|
|
8
|
-
use crate::json_store::context::JsonStoreContext;
|
|
9
|
-
use crate::json_store::types::{
|
|
10
|
-
JsonLoadRequestRef, JsonProjectionLoadRequestRef, JsonProjectionPath, JsonReadScopeRef,
|
|
11
|
-
JsonRef, JsonWritePlacementRef, NormalizedJsonRef,
|
|
12
|
-
};
|
|
13
|
-
use crate::live_state::LiveStateContext;
|
|
14
|
-
use crate::session::SessionMode;
|
|
15
|
-
use crate::storage::{
|
|
16
|
-
KvGetGroup, KvGetRequest, KvScanRange, KvScanRequest, KvWriteBatch, StorageContext,
|
|
17
|
-
StorageWriteSet,
|
|
18
|
-
};
|
|
19
|
-
use crate::tracked_state::{
|
|
20
|
-
MaterializedTrackedStateRow, TrackedStateContext, TrackedStateDeltaRef,
|
|
21
|
-
TrackedStateDiffRequest, TrackedStateFilter, TrackedStateProjection, TrackedStateRowRequest,
|
|
22
|
-
TrackedStateScanRequest,
|
|
23
|
-
};
|
|
24
|
-
use crate::transaction::open_transaction;
|
|
25
|
-
use crate::transaction::types::{
|
|
26
|
-
TransactionJson, TransactionWrite, TransactionWriteMode, TransactionWriteRow,
|
|
27
|
-
};
|
|
28
|
-
use crate::untracked_state::{
|
|
29
|
-
MaterializedUntrackedStateRow, UntrackedStateContext, UntrackedStateFilter,
|
|
30
|
-
UntrackedStateProjection, UntrackedStateRowRequest, UntrackedStateScanRequest,
|
|
31
|
-
};
|
|
32
|
-
use crate::version::VersionContext;
|
|
33
|
-
use crate::{Backend, LixError, NullableKeyFilter};
|
|
34
|
-
use std::collections::{BTreeMap, HashSet};
|
|
35
|
-
use std::sync::atomic::{AtomicUsize, Ordering};
|
|
36
|
-
use std::sync::Arc;
|
|
37
|
-
use std::sync::Mutex;
|
|
38
|
-
use std::sync::OnceLock;
|
|
39
|
-
use std::time::{Duration, Instant};
|
|
40
|
-
|
|
41
|
-
fn prepare_json_ref(document: &[u8]) -> Result<JsonRef, LixError> {
|
|
42
|
-
let text = std::str::from_utf8(document).map_err(|error| {
|
|
43
|
-
LixError::new(
|
|
44
|
-
LixError::CODE_UNKNOWN,
|
|
45
|
-
format!("benchmark JSON document is invalid UTF-8: {error}"),
|
|
46
|
-
)
|
|
47
|
-
})?;
|
|
48
|
-
Ok(JsonRef::for_content(text.as_bytes()))
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
#[derive(Debug, Clone, Copy)]
|
|
52
|
-
pub struct StorageBenchConfig {
|
|
53
|
-
pub rows: usize,
|
|
54
|
-
pub blob_bytes: usize,
|
|
55
|
-
pub state_payload_bytes: usize,
|
|
56
|
-
pub key_pattern: StorageBenchKeyPattern,
|
|
57
|
-
pub selectivity: StorageBenchSelectivity,
|
|
58
|
-
pub update_fraction: StorageBenchUpdateFraction,
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
impl StorageBenchConfig {
|
|
62
|
-
pub fn with_rows(mut self, rows: usize) -> Self {
|
|
63
|
-
self.rows = rows;
|
|
64
|
-
self
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
pub fn with_blob_bytes(mut self, blob_bytes: usize) -> Self {
|
|
68
|
-
self.blob_bytes = blob_bytes;
|
|
69
|
-
self
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
pub fn with_state_payload_bytes(mut self, state_payload_bytes: usize) -> Self {
|
|
73
|
-
self.state_payload_bytes = state_payload_bytes;
|
|
74
|
-
self
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
pub fn with_key_pattern(mut self, key_pattern: StorageBenchKeyPattern) -> Self {
|
|
78
|
-
self.key_pattern = key_pattern;
|
|
79
|
-
self
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
pub fn with_selectivity(mut self, selectivity: StorageBenchSelectivity) -> Self {
|
|
83
|
-
self.selectivity = selectivity;
|
|
84
|
-
self
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
pub fn with_update_fraction(mut self, update_fraction: StorageBenchUpdateFraction) -> Self {
|
|
88
|
-
self.update_fraction = update_fraction;
|
|
89
|
-
self
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
#[derive(Debug, Clone, Copy)]
|
|
94
|
-
pub enum StorageBenchKeyPattern {
|
|
95
|
-
Sequential,
|
|
96
|
-
Random,
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
#[derive(Debug, Clone, Copy)]
|
|
100
|
-
pub enum StorageBenchSelectivity {
|
|
101
|
-
Percent1,
|
|
102
|
-
Percent10,
|
|
103
|
-
Percent100,
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
impl StorageBenchSelectivity {
|
|
107
|
-
fn matches(self, index: usize) -> bool {
|
|
108
|
-
match self {
|
|
109
|
-
Self::Percent1 => index % 100 == 0,
|
|
110
|
-
Self::Percent10 => index % 10 == 0,
|
|
111
|
-
Self::Percent100 => true,
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
fn expected_rows(self, rows: usize) -> usize {
|
|
116
|
-
(0..rows).filter(|index| self.matches(*index)).count()
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
#[derive(Debug, Clone, Copy)]
|
|
121
|
-
pub enum StorageBenchUpdateFraction {
|
|
122
|
-
Percent10,
|
|
123
|
-
Percent100,
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
impl StorageBenchUpdateFraction {
|
|
127
|
-
fn rows(self, total_rows: usize) -> usize {
|
|
128
|
-
match self {
|
|
129
|
-
Self::Percent10 => total_rows.div_ceil(10),
|
|
130
|
-
Self::Percent100 => total_rows,
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
#[derive(Debug, Clone, Copy)]
|
|
136
|
-
pub struct StorageBenchReport {
|
|
137
|
-
pub measured_rows: usize,
|
|
138
|
-
pub verified_rows: usize,
|
|
139
|
-
pub elapsed: Duration,
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
|
143
|
-
pub struct TransactionBenchCounters {
|
|
144
|
-
pub rows_staged: usize,
|
|
145
|
-
pub untracked_rows: usize,
|
|
146
|
-
pub validation_version_count: usize,
|
|
147
|
-
pub schema_catalog_loads: usize,
|
|
148
|
-
pub json_store_stage_bytes_calls: usize,
|
|
149
|
-
pub unique_json_refs: usize,
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
|
153
|
-
pub struct TransactionAccountingReport {
|
|
154
|
-
pub counters: TransactionBenchCounters,
|
|
155
|
-
pub storage_write_batches: usize,
|
|
156
|
-
pub kv_puts_by_namespace: BTreeMap<String, usize>,
|
|
157
|
-
pub bytes_by_namespace: BTreeMap<String, usize>,
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
pub struct StorageApiFixture {
|
|
161
|
-
storage: StorageContext,
|
|
162
|
-
rows: usize,
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
pub struct TransactionBenchFixture {
|
|
166
|
-
storage: StorageContext,
|
|
167
|
-
live_state: Arc<LiveStateContext>,
|
|
168
|
-
tracked_state: Arc<TrackedStateContext>,
|
|
169
|
-
binary_cas: Arc<BinaryCasContext>,
|
|
170
|
-
commit_store: Arc<CommitStoreContext>,
|
|
171
|
-
version_ctx: Arc<VersionContext>,
|
|
172
|
-
catalog_context: Arc<CatalogContext>,
|
|
173
|
-
rows: Vec<TransactionWriteRow>,
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
pub struct TransactionCommitOnlyFixture {
|
|
177
|
-
runtime_functions: crate::functions::FunctionContext,
|
|
178
|
-
transaction: crate::transaction::Transaction,
|
|
179
|
-
rows: usize,
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
static TRANSACTION_ROWS_STAGED: AtomicUsize = AtomicUsize::new(0);
|
|
183
|
-
static TRANSACTION_UNTRACKED_ROWS: AtomicUsize = AtomicUsize::new(0);
|
|
184
|
-
static TRANSACTION_VALIDATION_VERSION_COUNT: AtomicUsize = AtomicUsize::new(0);
|
|
185
|
-
static TRANSACTION_SCHEMA_CATALOG_LOADS: AtomicUsize = AtomicUsize::new(0);
|
|
186
|
-
static JSON_STORE_STAGE_BYTES_CALLS: AtomicUsize = AtomicUsize::new(0);
|
|
187
|
-
static JSON_STORE_UNIQUE_REFS: OnceLock<Mutex<HashSet<[u8; 32]>>> = OnceLock::new();
|
|
188
|
-
|
|
189
|
-
const STORAGE_API_NAMESPACE: &str = "bench.storage_api";
|
|
190
|
-
const STORAGE_API_ALT_NAMESPACE: &str = "bench.storage_api.alt";
|
|
191
|
-
const TRANSACTION_BENCH_SCHEMA_KEY: &str = "bench_transaction_entity";
|
|
192
|
-
|
|
193
|
-
pub fn reset_transaction_bench_counters() {
|
|
194
|
-
TRANSACTION_ROWS_STAGED.store(0, Ordering::Relaxed);
|
|
195
|
-
TRANSACTION_UNTRACKED_ROWS.store(0, Ordering::Relaxed);
|
|
196
|
-
TRANSACTION_VALIDATION_VERSION_COUNT.store(0, Ordering::Relaxed);
|
|
197
|
-
TRANSACTION_SCHEMA_CATALOG_LOADS.store(0, Ordering::Relaxed);
|
|
198
|
-
JSON_STORE_STAGE_BYTES_CALLS.store(0, Ordering::Relaxed);
|
|
199
|
-
json_store_unique_refs()
|
|
200
|
-
.lock()
|
|
201
|
-
.expect("json store unique ref counter mutex should lock")
|
|
202
|
-
.clear();
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
pub fn transaction_bench_counters() -> TransactionBenchCounters {
|
|
206
|
-
TransactionBenchCounters {
|
|
207
|
-
rows_staged: TRANSACTION_ROWS_STAGED.load(Ordering::Relaxed),
|
|
208
|
-
untracked_rows: TRANSACTION_UNTRACKED_ROWS.load(Ordering::Relaxed),
|
|
209
|
-
validation_version_count: TRANSACTION_VALIDATION_VERSION_COUNT.load(Ordering::Relaxed),
|
|
210
|
-
schema_catalog_loads: TRANSACTION_SCHEMA_CATALOG_LOADS.load(Ordering::Relaxed),
|
|
211
|
-
json_store_stage_bytes_calls: JSON_STORE_STAGE_BYTES_CALLS.load(Ordering::Relaxed),
|
|
212
|
-
unique_json_refs: json_store_unique_refs()
|
|
213
|
-
.lock()
|
|
214
|
-
.expect("json store unique ref counter mutex should lock")
|
|
215
|
-
.len(),
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
pub(crate) fn record_transaction_rows_staged(rows: usize) {
|
|
220
|
-
TRANSACTION_ROWS_STAGED.fetch_add(rows, Ordering::Relaxed);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
pub(crate) fn record_transaction_untracked_rows(rows: usize) {
|
|
224
|
-
TRANSACTION_UNTRACKED_ROWS.fetch_add(rows, Ordering::Relaxed);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
pub(crate) fn record_transaction_validation_version() {
|
|
228
|
-
TRANSACTION_VALIDATION_VERSION_COUNT.fetch_add(1, Ordering::Relaxed);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
pub(crate) fn record_transaction_schema_catalog_load() {
|
|
232
|
-
TRANSACTION_SCHEMA_CATALOG_LOADS.fetch_add(1, Ordering::Relaxed);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
pub(crate) fn record_json_store_stage_bytes(hash: [u8; 32]) {
|
|
236
|
-
JSON_STORE_STAGE_BYTES_CALLS.fetch_add(1, Ordering::Relaxed);
|
|
237
|
-
json_store_unique_refs()
|
|
238
|
-
.lock()
|
|
239
|
-
.expect("json store unique ref counter mutex should lock")
|
|
240
|
-
.insert(hash);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
fn json_store_unique_refs() -> &'static Mutex<HashSet<[u8; 32]>> {
|
|
244
|
-
JSON_STORE_UNIQUE_REFS.get_or_init(|| Mutex::new(HashSet::new()))
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
pub async fn prepare_transaction_commit_empty(
|
|
248
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
249
|
-
) -> Result<TransactionBenchFixture, LixError> {
|
|
250
|
-
prepare_transaction_fixture(backend, Vec::new()).await
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
pub async fn prepare_transaction_commit_schema_only(
|
|
254
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
255
|
-
) -> Result<TransactionBenchFixture, LixError> {
|
|
256
|
-
prepare_transaction_fixture(backend, vec![transaction_registered_schema_row()]).await
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
pub async fn prepare_transaction_commit_entities_no_payload(
|
|
260
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
261
|
-
rows: usize,
|
|
262
|
-
) -> Result<TransactionBenchFixture, LixError> {
|
|
263
|
-
prepare_transaction_fixture(
|
|
264
|
-
backend,
|
|
265
|
-
transaction_entity_rows(TransactionEntityRows {
|
|
266
|
-
rows,
|
|
267
|
-
payload_bytes: 0,
|
|
268
|
-
payload_pattern: TransactionPayloadPattern::Unique,
|
|
269
|
-
metadata_pattern: TransactionPayloadPattern::None,
|
|
270
|
-
untracked: false,
|
|
271
|
-
key_prefix: "entity-no-payload",
|
|
272
|
-
}),
|
|
273
|
-
)
|
|
274
|
-
.await
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
pub async fn prepare_transaction_commit_entities_payload_1k_unique(
|
|
278
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
279
|
-
rows: usize,
|
|
280
|
-
) -> Result<TransactionBenchFixture, LixError> {
|
|
281
|
-
prepare_transaction_payload_fixture(
|
|
282
|
-
backend,
|
|
283
|
-
rows,
|
|
284
|
-
1024,
|
|
285
|
-
TransactionPayloadPattern::Unique,
|
|
286
|
-
false,
|
|
287
|
-
"entity-payload-1k-unique",
|
|
288
|
-
)
|
|
289
|
-
.await
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
pub async fn prepare_transaction_commit_entities_payload_1k_same(
|
|
293
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
294
|
-
rows: usize,
|
|
295
|
-
) -> Result<TransactionBenchFixture, LixError> {
|
|
296
|
-
prepare_transaction_payload_fixture(
|
|
297
|
-
backend,
|
|
298
|
-
rows,
|
|
299
|
-
1024,
|
|
300
|
-
TransactionPayloadPattern::Same,
|
|
301
|
-
false,
|
|
302
|
-
"entity-payload-1k-same",
|
|
303
|
-
)
|
|
304
|
-
.await
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
pub async fn prepare_transaction_commit_entities_payload_1k_half_duplicate(
|
|
308
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
309
|
-
rows: usize,
|
|
310
|
-
) -> Result<TransactionBenchFixture, LixError> {
|
|
311
|
-
prepare_transaction_payload_fixture(
|
|
312
|
-
backend,
|
|
313
|
-
rows,
|
|
314
|
-
1024,
|
|
315
|
-
TransactionPayloadPattern::HalfDuplicate,
|
|
316
|
-
false,
|
|
317
|
-
"entity-payload-1k-half-duplicate",
|
|
318
|
-
)
|
|
319
|
-
.await
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
pub async fn prepare_transaction_commit_entities_metadata_1k_same(
|
|
323
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
324
|
-
rows: usize,
|
|
325
|
-
) -> Result<TransactionBenchFixture, LixError> {
|
|
326
|
-
prepare_transaction_fixture(
|
|
327
|
-
backend,
|
|
328
|
-
transaction_entity_rows(TransactionEntityRows {
|
|
329
|
-
rows,
|
|
330
|
-
payload_bytes: 0,
|
|
331
|
-
payload_pattern: TransactionPayloadPattern::Unique,
|
|
332
|
-
metadata_pattern: TransactionPayloadPattern::Same,
|
|
333
|
-
untracked: false,
|
|
334
|
-
key_prefix: "entity-metadata-1k-same",
|
|
335
|
-
}),
|
|
336
|
-
)
|
|
337
|
-
.await
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
pub async fn prepare_transaction_commit_entities_payload_16k_unique(
|
|
341
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
342
|
-
rows: usize,
|
|
343
|
-
) -> Result<TransactionBenchFixture, LixError> {
|
|
344
|
-
prepare_transaction_payload_fixture(
|
|
345
|
-
backend,
|
|
346
|
-
rows,
|
|
347
|
-
16 * 1024,
|
|
348
|
-
TransactionPayloadPattern::Unique,
|
|
349
|
-
false,
|
|
350
|
-
"entity-payload-16k-unique",
|
|
351
|
-
)
|
|
352
|
-
.await
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
pub async fn prepare_transaction_commit_untracked_payload_1k_same(
|
|
356
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
357
|
-
rows: usize,
|
|
358
|
-
) -> Result<TransactionBenchFixture, LixError> {
|
|
359
|
-
prepare_transaction_payload_fixture(
|
|
360
|
-
backend,
|
|
361
|
-
rows,
|
|
362
|
-
1024,
|
|
363
|
-
TransactionPayloadPattern::Same,
|
|
364
|
-
true,
|
|
365
|
-
"untracked-payload-1k-same",
|
|
366
|
-
)
|
|
367
|
-
.await
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
pub async fn prepare_transaction_update_existing_payload_1k(
|
|
371
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
372
|
-
root_rows: usize,
|
|
373
|
-
update_rows: usize,
|
|
374
|
-
) -> Result<TransactionBenchFixture, LixError> {
|
|
375
|
-
let fixture = prepare_transaction_payload_fixture(
|
|
376
|
-
backend,
|
|
377
|
-
root_rows,
|
|
378
|
-
1024,
|
|
379
|
-
TransactionPayloadPattern::Unique,
|
|
380
|
-
false,
|
|
381
|
-
"update-existing-root",
|
|
382
|
-
)
|
|
383
|
-
.await?;
|
|
384
|
-
transaction_commit_prepared(&fixture).await?;
|
|
385
|
-
let rows = transaction_entity_rows(TransactionEntityRows {
|
|
386
|
-
rows: update_rows,
|
|
387
|
-
payload_bytes: 1024,
|
|
388
|
-
payload_pattern: TransactionPayloadPattern::Unique,
|
|
389
|
-
metadata_pattern: TransactionPayloadPattern::None,
|
|
390
|
-
untracked: false,
|
|
391
|
-
key_prefix: "update-existing-root",
|
|
392
|
-
});
|
|
393
|
-
Ok(TransactionBenchFixture { rows, ..fixture })
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
pub async fn transaction_commit_prepared(
|
|
397
|
-
fixture: &TransactionBenchFixture,
|
|
398
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
399
|
-
let opened = open_transaction(
|
|
400
|
-
&SessionMode::Pinned {
|
|
401
|
-
version_id: crate::GLOBAL_VERSION_ID.to_string(),
|
|
402
|
-
},
|
|
403
|
-
fixture.storage.clone(),
|
|
404
|
-
Arc::clone(&fixture.live_state),
|
|
405
|
-
Arc::clone(&fixture.tracked_state),
|
|
406
|
-
Arc::clone(&fixture.binary_cas),
|
|
407
|
-
Arc::clone(&fixture.commit_store),
|
|
408
|
-
Arc::clone(&fixture.version_ctx),
|
|
409
|
-
Arc::clone(&fixture.catalog_context),
|
|
410
|
-
)
|
|
411
|
-
.await?;
|
|
412
|
-
let mut transaction = opened.transaction;
|
|
413
|
-
let runtime_functions = opened.runtime_functions;
|
|
414
|
-
let started_at = Instant::now();
|
|
415
|
-
if !fixture.rows.is_empty() {
|
|
416
|
-
transaction
|
|
417
|
-
.stage_write(TransactionWrite::Rows {
|
|
418
|
-
mode: TransactionWriteMode::Replace,
|
|
419
|
-
rows: fixture.rows.clone(),
|
|
420
|
-
})
|
|
421
|
-
.await?;
|
|
422
|
-
}
|
|
423
|
-
transaction.commit(&runtime_functions).await?;
|
|
424
|
-
Ok(StorageBenchReport {
|
|
425
|
-
measured_rows: fixture.rows.len(),
|
|
426
|
-
verified_rows: fixture.rows.len(),
|
|
427
|
-
elapsed: started_at.elapsed(),
|
|
428
|
-
})
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
pub async fn transaction_open_empty_prepared(
|
|
432
|
-
fixture: &TransactionBenchFixture,
|
|
433
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
434
|
-
let started_at = Instant::now();
|
|
435
|
-
let opened = open_transaction(
|
|
436
|
-
&SessionMode::Pinned {
|
|
437
|
-
version_id: crate::GLOBAL_VERSION_ID.to_string(),
|
|
438
|
-
},
|
|
439
|
-
fixture.storage.clone(),
|
|
440
|
-
Arc::clone(&fixture.live_state),
|
|
441
|
-
Arc::clone(&fixture.tracked_state),
|
|
442
|
-
Arc::clone(&fixture.binary_cas),
|
|
443
|
-
Arc::clone(&fixture.commit_store),
|
|
444
|
-
Arc::clone(&fixture.version_ctx),
|
|
445
|
-
Arc::clone(&fixture.catalog_context),
|
|
446
|
-
)
|
|
447
|
-
.await?;
|
|
448
|
-
let elapsed = started_at.elapsed();
|
|
449
|
-
opened.transaction.rollback().await?;
|
|
450
|
-
Ok(StorageBenchReport {
|
|
451
|
-
measured_rows: 0,
|
|
452
|
-
verified_rows: 0,
|
|
453
|
-
elapsed,
|
|
454
|
-
})
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
pub async fn transaction_stage_only_prepared(
|
|
458
|
-
fixture: &TransactionBenchFixture,
|
|
459
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
460
|
-
let opened = open_transaction(
|
|
461
|
-
&SessionMode::Pinned {
|
|
462
|
-
version_id: crate::GLOBAL_VERSION_ID.to_string(),
|
|
463
|
-
},
|
|
464
|
-
fixture.storage.clone(),
|
|
465
|
-
Arc::clone(&fixture.live_state),
|
|
466
|
-
Arc::clone(&fixture.tracked_state),
|
|
467
|
-
Arc::clone(&fixture.binary_cas),
|
|
468
|
-
Arc::clone(&fixture.commit_store),
|
|
469
|
-
Arc::clone(&fixture.version_ctx),
|
|
470
|
-
Arc::clone(&fixture.catalog_context),
|
|
471
|
-
)
|
|
472
|
-
.await?;
|
|
473
|
-
let mut transaction = opened.transaction;
|
|
474
|
-
let started_at = Instant::now();
|
|
475
|
-
if !fixture.rows.is_empty() {
|
|
476
|
-
transaction
|
|
477
|
-
.stage_write(TransactionWrite::Rows {
|
|
478
|
-
mode: TransactionWriteMode::Replace,
|
|
479
|
-
rows: fixture.rows.clone(),
|
|
480
|
-
})
|
|
481
|
-
.await?;
|
|
482
|
-
}
|
|
483
|
-
let elapsed = started_at.elapsed();
|
|
484
|
-
transaction.rollback().await?;
|
|
485
|
-
Ok(StorageBenchReport {
|
|
486
|
-
measured_rows: fixture.rows.len(),
|
|
487
|
-
verified_rows: fixture.rows.len(),
|
|
488
|
-
elapsed,
|
|
489
|
-
})
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
pub async fn prepare_transaction_commit_only(
|
|
493
|
-
fixture: TransactionBenchFixture,
|
|
494
|
-
) -> Result<TransactionCommitOnlyFixture, LixError> {
|
|
495
|
-
let opened = open_transaction(
|
|
496
|
-
&SessionMode::Pinned {
|
|
497
|
-
version_id: crate::GLOBAL_VERSION_ID.to_string(),
|
|
498
|
-
},
|
|
499
|
-
fixture.storage.clone(),
|
|
500
|
-
Arc::clone(&fixture.live_state),
|
|
501
|
-
Arc::clone(&fixture.tracked_state),
|
|
502
|
-
Arc::clone(&fixture.binary_cas),
|
|
503
|
-
Arc::clone(&fixture.commit_store),
|
|
504
|
-
Arc::clone(&fixture.version_ctx),
|
|
505
|
-
Arc::clone(&fixture.catalog_context),
|
|
506
|
-
)
|
|
507
|
-
.await?;
|
|
508
|
-
let mut transaction = opened.transaction;
|
|
509
|
-
let runtime_functions = opened.runtime_functions;
|
|
510
|
-
let rows = fixture.rows.len();
|
|
511
|
-
if !fixture.rows.is_empty() {
|
|
512
|
-
transaction
|
|
513
|
-
.stage_write(TransactionWrite::Rows {
|
|
514
|
-
mode: TransactionWriteMode::Replace,
|
|
515
|
-
rows: fixture.rows,
|
|
516
|
-
})
|
|
517
|
-
.await?;
|
|
518
|
-
}
|
|
519
|
-
Ok(TransactionCommitOnlyFixture {
|
|
520
|
-
runtime_functions,
|
|
521
|
-
transaction,
|
|
522
|
-
rows,
|
|
523
|
-
})
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
pub async fn transaction_commit_only_prepared(
|
|
527
|
-
fixture: TransactionCommitOnlyFixture,
|
|
528
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
529
|
-
let rows = fixture.rows;
|
|
530
|
-
let started_at = Instant::now();
|
|
531
|
-
fixture
|
|
532
|
-
.transaction
|
|
533
|
-
.commit(&fixture.runtime_functions)
|
|
534
|
-
.await?;
|
|
535
|
-
Ok(StorageBenchReport {
|
|
536
|
-
measured_rows: rows,
|
|
537
|
-
verified_rows: rows,
|
|
538
|
-
elapsed: started_at.elapsed(),
|
|
539
|
-
})
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
async fn prepare_transaction_payload_fixture(
|
|
543
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
544
|
-
rows: usize,
|
|
545
|
-
payload_bytes: usize,
|
|
546
|
-
payload_pattern: TransactionPayloadPattern,
|
|
547
|
-
untracked: bool,
|
|
548
|
-
key_prefix: &'static str,
|
|
549
|
-
) -> Result<TransactionBenchFixture, LixError> {
|
|
550
|
-
prepare_transaction_fixture(
|
|
551
|
-
backend,
|
|
552
|
-
transaction_entity_rows(TransactionEntityRows {
|
|
553
|
-
rows,
|
|
554
|
-
payload_bytes,
|
|
555
|
-
payload_pattern,
|
|
556
|
-
metadata_pattern: TransactionPayloadPattern::None,
|
|
557
|
-
untracked,
|
|
558
|
-
key_prefix,
|
|
559
|
-
}),
|
|
560
|
-
)
|
|
561
|
-
.await
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
async fn prepare_transaction_fixture(
|
|
565
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
566
|
-
rows: Vec<TransactionWriteRow>,
|
|
567
|
-
) -> Result<TransactionBenchFixture, LixError> {
|
|
568
|
-
let storage = StorageContext::new(backend);
|
|
569
|
-
let tracked_state = Arc::new(TrackedStateContext::new());
|
|
570
|
-
let untracked_state = Arc::new(UntrackedStateContext::new());
|
|
571
|
-
let commit_store = Arc::new(CommitStoreContext::new());
|
|
572
|
-
let live_state = Arc::new(LiveStateContext::new(
|
|
573
|
-
tracked_state.as_ref().clone(),
|
|
574
|
-
untracked_state.as_ref().clone(),
|
|
575
|
-
crate::commit_graph::CommitGraphContext::new(),
|
|
576
|
-
));
|
|
577
|
-
let binary_cas = Arc::new(BinaryCasContext::new());
|
|
578
|
-
let version_ctx = Arc::new(VersionContext::new(untracked_state));
|
|
579
|
-
let catalog_context = Arc::new(CatalogContext::new());
|
|
580
|
-
seed_transaction_visible_schema_rows(storage.clone()).await?;
|
|
581
|
-
Ok(TransactionBenchFixture {
|
|
582
|
-
storage,
|
|
583
|
-
live_state,
|
|
584
|
-
tracked_state,
|
|
585
|
-
binary_cas,
|
|
586
|
-
commit_store,
|
|
587
|
-
version_ctx,
|
|
588
|
-
catalog_context,
|
|
589
|
-
rows,
|
|
590
|
-
})
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
async fn seed_transaction_visible_schema_rows(storage: StorageContext) -> Result<(), LixError> {
|
|
594
|
-
let mut writes = StorageWriteSet::new();
|
|
595
|
-
let rows = crate::schema::seed_schema_definitions()
|
|
596
|
-
.into_iter()
|
|
597
|
-
.cloned()
|
|
598
|
-
.chain(std::iter::once(transaction_entity_schema_definition()))
|
|
599
|
-
.map(|schema| {
|
|
600
|
-
let key = crate::schema::schema_key_from_definition(&schema)
|
|
601
|
-
.expect("seed schema key should derive");
|
|
602
|
-
let snapshot_content = serde_json::json!({ "value": schema }).to_string();
|
|
603
|
-
Ok(crate::untracked_state::UntrackedStateRow {
|
|
604
|
-
entity_id: crate::schema::registered_schema_entity_id(&key.schema_key)
|
|
605
|
-
.expect("registered schema identity should derive"),
|
|
606
|
-
schema_key: "lix_registered_schema".to_string(),
|
|
607
|
-
file_id: None,
|
|
608
|
-
version_id: crate::GLOBAL_VERSION_ID.to_string(),
|
|
609
|
-
snapshot_content: Some(snapshot_content),
|
|
610
|
-
metadata: None,
|
|
611
|
-
created_at: "1970-01-01T00:00:00.000Z".to_string(),
|
|
612
|
-
updated_at: "1970-01-01T00:00:00.000Z".to_string(),
|
|
613
|
-
global: true,
|
|
614
|
-
})
|
|
615
|
-
})
|
|
616
|
-
.collect::<Result<Vec<_>, LixError>>()?;
|
|
617
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
618
|
-
UntrackedStateContext::new()
|
|
619
|
-
.writer(&mut writes)
|
|
620
|
-
.stage_rows(rows.iter().map(|row| row.as_ref()))?;
|
|
621
|
-
writes.apply(&mut transaction.as_mut()).await?;
|
|
622
|
-
transaction.commit().await
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
fn transaction_entity_schema_definition() -> serde_json::Value {
|
|
626
|
-
serde_json::json!({
|
|
627
|
-
"x-lix-key": TRANSACTION_BENCH_SCHEMA_KEY,
|
|
628
|
-
"type": "object",
|
|
629
|
-
"properties": {
|
|
630
|
-
"value": {
|
|
631
|
-
"anyOf": [
|
|
632
|
-
{ "type": "string" },
|
|
633
|
-
{ "type": "object" },
|
|
634
|
-
{ "type": "array" },
|
|
635
|
-
{ "type": "number" },
|
|
636
|
-
{ "type": "boolean" },
|
|
637
|
-
{ "type": "null" }
|
|
638
|
-
]
|
|
639
|
-
}
|
|
640
|
-
},
|
|
641
|
-
"required": ["value"],
|
|
642
|
-
"additionalProperties": false
|
|
643
|
-
})
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
#[derive(Debug, Clone, Copy)]
|
|
647
|
-
enum TransactionPayloadPattern {
|
|
648
|
-
None,
|
|
649
|
-
Unique,
|
|
650
|
-
Same,
|
|
651
|
-
HalfDuplicate,
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
struct TransactionEntityRows {
|
|
655
|
-
rows: usize,
|
|
656
|
-
payload_bytes: usize,
|
|
657
|
-
payload_pattern: TransactionPayloadPattern,
|
|
658
|
-
metadata_pattern: TransactionPayloadPattern,
|
|
659
|
-
untracked: bool,
|
|
660
|
-
key_prefix: &'static str,
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
fn transaction_entity_rows(config: TransactionEntityRows) -> Vec<TransactionWriteRow> {
|
|
664
|
-
(0..config.rows)
|
|
665
|
-
.map(|index| {
|
|
666
|
-
let key = format!("{}-{index:06}", config.key_prefix);
|
|
667
|
-
let value_index = payload_pattern_index(config.payload_pattern, index);
|
|
668
|
-
let metadata_index = payload_pattern_index(config.metadata_pattern, index);
|
|
669
|
-
TransactionWriteRow {
|
|
670
|
-
entity_id: Some(EntityIdentity::single(key.clone())),
|
|
671
|
-
schema_key: TRANSACTION_BENCH_SCHEMA_KEY.to_string(),
|
|
672
|
-
file_id: None,
|
|
673
|
-
snapshot: Some(transaction_snapshot_json(
|
|
674
|
-
&key,
|
|
675
|
-
value_index,
|
|
676
|
-
config.payload_bytes,
|
|
677
|
-
)),
|
|
678
|
-
metadata: transaction_metadata(config.metadata_pattern, metadata_index),
|
|
679
|
-
origin: None,
|
|
680
|
-
created_at: None,
|
|
681
|
-
updated_at: None,
|
|
682
|
-
global: true,
|
|
683
|
-
change_id: None,
|
|
684
|
-
commit_id: None,
|
|
685
|
-
untracked: config.untracked,
|
|
686
|
-
version_id: crate::GLOBAL_VERSION_ID.to_string(),
|
|
687
|
-
}
|
|
688
|
-
})
|
|
689
|
-
.collect()
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
fn transaction_registered_schema_row() -> TransactionWriteRow {
|
|
693
|
-
let schema = serde_json::json!({
|
|
694
|
-
"x-lix-key": "bench_transaction_schema",
|
|
695
|
-
"x-lix-primary-key": ["/id"],
|
|
696
|
-
"type": "object",
|
|
697
|
-
"properties": {
|
|
698
|
-
"id": { "type": "string" },
|
|
699
|
-
"value": { "type": "string" }
|
|
700
|
-
},
|
|
701
|
-
"required": ["id", "value"],
|
|
702
|
-
"additionalProperties": false
|
|
703
|
-
});
|
|
704
|
-
let key =
|
|
705
|
-
crate::schema::schema_key_from_definition(&schema).expect("seed schema key should derive");
|
|
706
|
-
TransactionWriteRow {
|
|
707
|
-
entity_id: Some(
|
|
708
|
-
crate::schema::registered_schema_entity_id(&key.schema_key)
|
|
709
|
-
.expect("registered schema identity should derive"),
|
|
710
|
-
),
|
|
711
|
-
schema_key: "lix_registered_schema".to_string(),
|
|
712
|
-
file_id: None,
|
|
713
|
-
snapshot: Some(TransactionJson::from_value_unchecked(
|
|
714
|
-
serde_json::json!({ "value": schema }),
|
|
715
|
-
)),
|
|
716
|
-
metadata: None,
|
|
717
|
-
origin: None,
|
|
718
|
-
created_at: None,
|
|
719
|
-
updated_at: None,
|
|
720
|
-
global: true,
|
|
721
|
-
change_id: None,
|
|
722
|
-
commit_id: None,
|
|
723
|
-
untracked: false,
|
|
724
|
-
version_id: crate::GLOBAL_VERSION_ID.to_string(),
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
fn transaction_snapshot_json(
|
|
729
|
-
_key: &str,
|
|
730
|
-
payload_index: usize,
|
|
731
|
-
target_bytes: usize,
|
|
732
|
-
) -> TransactionJson {
|
|
733
|
-
let base_value = format!("/entities/{payload_index}/value");
|
|
734
|
-
let value = if target_bytes == 0 {
|
|
735
|
-
base_value
|
|
736
|
-
} else {
|
|
737
|
-
let current = serde_json::json!({
|
|
738
|
-
"value": base_value,
|
|
739
|
-
})
|
|
740
|
-
.to_string()
|
|
741
|
-
.len();
|
|
742
|
-
let padding = target_bytes.saturating_sub(current);
|
|
743
|
-
format!("{base_value}:{}", "x".repeat(padding))
|
|
744
|
-
};
|
|
745
|
-
let mut object = serde_json::Map::new();
|
|
746
|
-
object.insert("value".to_string(), serde_json::Value::String(value));
|
|
747
|
-
TransactionJson::from_value_unchecked(serde_json::Value::Object(object))
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
fn transaction_metadata(
|
|
751
|
-
pattern: TransactionPayloadPattern,
|
|
752
|
-
metadata_index: usize,
|
|
753
|
-
) -> Option<TransactionJson> {
|
|
754
|
-
match pattern {
|
|
755
|
-
TransactionPayloadPattern::None => None,
|
|
756
|
-
TransactionPayloadPattern::Unique
|
|
757
|
-
| TransactionPayloadPattern::Same
|
|
758
|
-
| TransactionPayloadPattern::HalfDuplicate => {
|
|
759
|
-
let mut object = serde_json::Map::new();
|
|
760
|
-
object.insert(
|
|
761
|
-
"source".to_string(),
|
|
762
|
-
serde_json::Value::String("transaction-bench".to_string()),
|
|
763
|
-
);
|
|
764
|
-
object.insert(
|
|
765
|
-
"metadata_index".to_string(),
|
|
766
|
-
serde_json::Value::String(metadata_index.to_string()),
|
|
767
|
-
);
|
|
768
|
-
pad_json_object(&mut object, 1024);
|
|
769
|
-
Some(TransactionJson::from_value_unchecked(
|
|
770
|
-
serde_json::Value::Object(object),
|
|
771
|
-
))
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
fn payload_pattern_index(pattern: TransactionPayloadPattern, index: usize) -> usize {
|
|
777
|
-
match pattern {
|
|
778
|
-
TransactionPayloadPattern::None | TransactionPayloadPattern::Unique => index,
|
|
779
|
-
TransactionPayloadPattern::Same => 0,
|
|
780
|
-
TransactionPayloadPattern::HalfDuplicate => index % 2,
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
pub async fn storage_api_write_kv_batch_puts(
|
|
785
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
786
|
-
rows: usize,
|
|
787
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
788
|
-
let storage = StorageContext::new(backend);
|
|
789
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
790
|
-
let mut batch = KvWriteBatch::new();
|
|
791
|
-
for index in 0..rows {
|
|
792
|
-
batch.put(
|
|
793
|
-
STORAGE_API_NAMESPACE,
|
|
794
|
-
storage_api_key(index),
|
|
795
|
-
storage_api_value(index),
|
|
796
|
-
);
|
|
797
|
-
}
|
|
798
|
-
let started_at = Instant::now();
|
|
799
|
-
let stats = transaction.write_kv_batch(batch).await?;
|
|
800
|
-
transaction.commit().await?;
|
|
801
|
-
Ok(StorageBenchReport {
|
|
802
|
-
measured_rows: stats.puts,
|
|
803
|
-
verified_rows: rows,
|
|
804
|
-
elapsed: started_at.elapsed(),
|
|
805
|
-
})
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
pub async fn storage_api_write_kv_batch_mixed_put_delete(
|
|
809
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
810
|
-
rows: usize,
|
|
811
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
812
|
-
let fixture = prepare_storage_api_read(backend, rows).await?;
|
|
813
|
-
let mut transaction = fixture.storage.begin_write_transaction().await?;
|
|
814
|
-
let mut batch = KvWriteBatch::new();
|
|
815
|
-
for index in 0..rows {
|
|
816
|
-
if index % 2 == 0 {
|
|
817
|
-
batch.put(
|
|
818
|
-
STORAGE_API_NAMESPACE,
|
|
819
|
-
storage_api_key(index),
|
|
820
|
-
storage_api_updated_value(index),
|
|
821
|
-
);
|
|
822
|
-
} else {
|
|
823
|
-
batch.delete(STORAGE_API_NAMESPACE, storage_api_key(index));
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
let started_at = Instant::now();
|
|
827
|
-
let stats = transaction.write_kv_batch(batch).await?;
|
|
828
|
-
transaction.commit().await?;
|
|
829
|
-
Ok(StorageBenchReport {
|
|
830
|
-
measured_rows: stats.puts + stats.deletes,
|
|
831
|
-
verified_rows: rows,
|
|
832
|
-
elapsed: started_at.elapsed(),
|
|
833
|
-
})
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
pub async fn storage_api_write_kv_batch_multi_namespace(
|
|
837
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
838
|
-
rows: usize,
|
|
839
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
840
|
-
let storage = StorageContext::new(backend);
|
|
841
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
842
|
-
let mut batch = KvWriteBatch::new();
|
|
843
|
-
for index in 0..rows {
|
|
844
|
-
let namespace = if index % 2 == 0 {
|
|
845
|
-
STORAGE_API_NAMESPACE
|
|
846
|
-
} else {
|
|
847
|
-
STORAGE_API_ALT_NAMESPACE
|
|
848
|
-
};
|
|
849
|
-
batch.put(namespace, storage_api_key(index), storage_api_value(index));
|
|
850
|
-
}
|
|
851
|
-
let started_at = Instant::now();
|
|
852
|
-
let stats = transaction.write_kv_batch(batch).await?;
|
|
853
|
-
transaction.commit().await?;
|
|
854
|
-
Ok(StorageBenchReport {
|
|
855
|
-
measured_rows: stats.puts,
|
|
856
|
-
verified_rows: rows,
|
|
857
|
-
elapsed: started_at.elapsed(),
|
|
858
|
-
})
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
pub async fn storage_api_write_kv_batch_duplicate_keys(
|
|
862
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
863
|
-
rows: usize,
|
|
864
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
865
|
-
let storage = StorageContext::new(backend);
|
|
866
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
867
|
-
let mut batch = KvWriteBatch::new();
|
|
868
|
-
for index in 0..rows {
|
|
869
|
-
batch.put(
|
|
870
|
-
STORAGE_API_NAMESPACE,
|
|
871
|
-
storage_api_key(index % 100),
|
|
872
|
-
storage_api_value(index),
|
|
873
|
-
);
|
|
874
|
-
}
|
|
875
|
-
let started_at = Instant::now();
|
|
876
|
-
let stats = transaction.write_kv_batch(batch).await?;
|
|
877
|
-
transaction.commit().await?;
|
|
878
|
-
Ok(StorageBenchReport {
|
|
879
|
-
measured_rows: stats.puts,
|
|
880
|
-
verified_rows: rows,
|
|
881
|
-
elapsed: started_at.elapsed(),
|
|
882
|
-
})
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
pub async fn storage_api_write_kv_batch_value_size(
|
|
886
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
887
|
-
rows: usize,
|
|
888
|
-
value_bytes: usize,
|
|
889
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
890
|
-
let storage = StorageContext::new(backend);
|
|
891
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
892
|
-
let mut batch = KvWriteBatch::new();
|
|
893
|
-
for index in 0..rows {
|
|
894
|
-
batch.put(
|
|
895
|
-
STORAGE_API_NAMESPACE,
|
|
896
|
-
storage_api_key(index),
|
|
897
|
-
storage_api_value_with_bytes(index, value_bytes),
|
|
898
|
-
);
|
|
899
|
-
}
|
|
900
|
-
let started_at = Instant::now();
|
|
901
|
-
let stats = transaction.write_kv_batch(batch).await?;
|
|
902
|
-
transaction.commit().await?;
|
|
903
|
-
Ok(StorageBenchReport {
|
|
904
|
-
measured_rows: stats.puts,
|
|
905
|
-
verified_rows: rows,
|
|
906
|
-
elapsed: started_at.elapsed(),
|
|
907
|
-
})
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
pub async fn storage_api_write_and_commit(
|
|
911
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
912
|
-
rows: usize,
|
|
913
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
914
|
-
let storage = StorageContext::new(backend);
|
|
915
|
-
let started_at = Instant::now();
|
|
916
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
917
|
-
let mut batch = KvWriteBatch::new();
|
|
918
|
-
for index in 0..rows {
|
|
919
|
-
batch.put(
|
|
920
|
-
STORAGE_API_NAMESPACE,
|
|
921
|
-
storage_api_key(index),
|
|
922
|
-
storage_api_value(index),
|
|
923
|
-
);
|
|
924
|
-
}
|
|
925
|
-
let stats = transaction.write_kv_batch(batch).await?;
|
|
926
|
-
transaction.commit().await?;
|
|
927
|
-
Ok(StorageBenchReport {
|
|
928
|
-
measured_rows: stats.puts,
|
|
929
|
-
verified_rows: rows,
|
|
930
|
-
elapsed: started_at.elapsed(),
|
|
931
|
-
})
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
pub async fn storage_api_rollback_after_write(
|
|
935
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
936
|
-
rows: usize,
|
|
937
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
938
|
-
let storage = StorageContext::new(backend);
|
|
939
|
-
let started_at = Instant::now();
|
|
940
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
941
|
-
let mut batch = KvWriteBatch::new();
|
|
942
|
-
for index in 0..rows {
|
|
943
|
-
batch.put(
|
|
944
|
-
STORAGE_API_NAMESPACE,
|
|
945
|
-
storage_api_key(index),
|
|
946
|
-
storage_api_value(index),
|
|
947
|
-
);
|
|
948
|
-
}
|
|
949
|
-
let stats = transaction.write_kv_batch(batch).await?;
|
|
950
|
-
transaction.rollback().await?;
|
|
951
|
-
Ok(StorageBenchReport {
|
|
952
|
-
measured_rows: stats.puts,
|
|
953
|
-
verified_rows: rows,
|
|
954
|
-
elapsed: started_at.elapsed(),
|
|
955
|
-
})
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
pub async fn prepare_storage_api_read(
|
|
959
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
960
|
-
rows: usize,
|
|
961
|
-
) -> Result<StorageApiFixture, LixError> {
|
|
962
|
-
let storage = StorageContext::new(backend);
|
|
963
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
964
|
-
let mut batch = KvWriteBatch::new();
|
|
965
|
-
for index in 0..rows {
|
|
966
|
-
batch.put(
|
|
967
|
-
STORAGE_API_NAMESPACE,
|
|
968
|
-
storage_api_key(index),
|
|
969
|
-
storage_api_value(index),
|
|
970
|
-
);
|
|
971
|
-
}
|
|
972
|
-
transaction.write_kv_batch(batch).await?;
|
|
973
|
-
transaction.commit().await?;
|
|
974
|
-
Ok(StorageApiFixture { storage, rows })
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
pub async fn storage_api_get_values_hits_prepared(
|
|
978
|
-
fixture: &StorageApiFixture,
|
|
979
|
-
reads: usize,
|
|
980
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
981
|
-
let mut transaction = fixture.storage.begin_read_transaction().await?;
|
|
982
|
-
let keys = (0..reads)
|
|
983
|
-
.map(|index| storage_api_key(index % fixture.rows))
|
|
984
|
-
.collect::<Vec<_>>();
|
|
985
|
-
let started_at = Instant::now();
|
|
986
|
-
let result = transaction
|
|
987
|
-
.get_values(KvGetRequest {
|
|
988
|
-
groups: vec![KvGetGroup {
|
|
989
|
-
namespace: STORAGE_API_NAMESPACE.to_string(),
|
|
990
|
-
keys,
|
|
991
|
-
}],
|
|
992
|
-
})
|
|
993
|
-
.await?;
|
|
994
|
-
transaction.rollback().await?;
|
|
995
|
-
let verified_rows = result.groups[0]
|
|
996
|
-
.values_iter()
|
|
997
|
-
.filter(|value| value.is_some())
|
|
998
|
-
.count();
|
|
999
|
-
Ok(StorageBenchReport {
|
|
1000
|
-
measured_rows: reads,
|
|
1001
|
-
verified_rows,
|
|
1002
|
-
elapsed: started_at.elapsed(),
|
|
1003
|
-
})
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
pub async fn storage_api_exists_many_prepared(
|
|
1007
|
-
fixture: &StorageApiFixture,
|
|
1008
|
-
reads: usize,
|
|
1009
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1010
|
-
let mut transaction = fixture.storage.begin_read_transaction().await?;
|
|
1011
|
-
let keys = (0..reads)
|
|
1012
|
-
.map(|index| storage_api_key(index % fixture.rows))
|
|
1013
|
-
.collect::<Vec<_>>();
|
|
1014
|
-
let started_at = Instant::now();
|
|
1015
|
-
let result = transaction
|
|
1016
|
-
.exists_many(KvGetRequest {
|
|
1017
|
-
groups: vec![KvGetGroup {
|
|
1018
|
-
namespace: STORAGE_API_NAMESPACE.to_string(),
|
|
1019
|
-
keys,
|
|
1020
|
-
}],
|
|
1021
|
-
})
|
|
1022
|
-
.await?;
|
|
1023
|
-
transaction.rollback().await?;
|
|
1024
|
-
let verified_rows = result.groups[0]
|
|
1025
|
-
.exists
|
|
1026
|
-
.iter()
|
|
1027
|
-
.filter(|exists| **exists)
|
|
1028
|
-
.count();
|
|
1029
|
-
Ok(StorageBenchReport {
|
|
1030
|
-
measured_rows: reads,
|
|
1031
|
-
verified_rows,
|
|
1032
|
-
elapsed: started_at.elapsed(),
|
|
1033
|
-
})
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
pub async fn storage_api_get_values_misses_prepared(
|
|
1037
|
-
fixture: &StorageApiFixture,
|
|
1038
|
-
reads: usize,
|
|
1039
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1040
|
-
let mut transaction = fixture.storage.begin_read_transaction().await?;
|
|
1041
|
-
let keys = (0..reads)
|
|
1042
|
-
.map(|index| storage_api_missing_key(index))
|
|
1043
|
-
.collect::<Vec<_>>();
|
|
1044
|
-
let started_at = Instant::now();
|
|
1045
|
-
let result = transaction
|
|
1046
|
-
.get_values(KvGetRequest {
|
|
1047
|
-
groups: vec![KvGetGroup {
|
|
1048
|
-
namespace: STORAGE_API_NAMESPACE.to_string(),
|
|
1049
|
-
keys,
|
|
1050
|
-
}],
|
|
1051
|
-
})
|
|
1052
|
-
.await?;
|
|
1053
|
-
transaction.rollback().await?;
|
|
1054
|
-
let verified_rows = result.groups[0]
|
|
1055
|
-
.values_iter()
|
|
1056
|
-
.filter(|value| value.is_none())
|
|
1057
|
-
.count();
|
|
1058
|
-
Ok(StorageBenchReport {
|
|
1059
|
-
measured_rows: reads,
|
|
1060
|
-
verified_rows,
|
|
1061
|
-
elapsed: started_at.elapsed(),
|
|
1062
|
-
})
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
pub async fn storage_api_get_values_mixed_hit_miss_prepared(
|
|
1066
|
-
fixture: &StorageApiFixture,
|
|
1067
|
-
reads: usize,
|
|
1068
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1069
|
-
let mut transaction = fixture.storage.begin_read_transaction().await?;
|
|
1070
|
-
let keys = (0..reads)
|
|
1071
|
-
.map(|index| {
|
|
1072
|
-
if index % 2 == 0 {
|
|
1073
|
-
storage_api_key(index % fixture.rows)
|
|
1074
|
-
} else {
|
|
1075
|
-
storage_api_missing_key(index)
|
|
1076
|
-
}
|
|
1077
|
-
})
|
|
1078
|
-
.collect::<Vec<_>>();
|
|
1079
|
-
let started_at = Instant::now();
|
|
1080
|
-
let result = transaction
|
|
1081
|
-
.get_values(KvGetRequest {
|
|
1082
|
-
groups: vec![KvGetGroup {
|
|
1083
|
-
namespace: STORAGE_API_NAMESPACE.to_string(),
|
|
1084
|
-
keys,
|
|
1085
|
-
}],
|
|
1086
|
-
})
|
|
1087
|
-
.await?;
|
|
1088
|
-
transaction.rollback().await?;
|
|
1089
|
-
let verified_rows = result.groups[0]
|
|
1090
|
-
.values_iter()
|
|
1091
|
-
.filter(|value| value.is_some())
|
|
1092
|
-
.count();
|
|
1093
|
-
Ok(StorageBenchReport {
|
|
1094
|
-
measured_rows: reads,
|
|
1095
|
-
verified_rows,
|
|
1096
|
-
elapsed: started_at.elapsed(),
|
|
1097
|
-
})
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
pub async fn storage_api_get_values_multi_namespace(
|
|
1101
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
1102
|
-
reads: usize,
|
|
1103
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1104
|
-
let storage = StorageContext::new(backend);
|
|
1105
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
1106
|
-
let mut batch = KvWriteBatch::new();
|
|
1107
|
-
for index in 0..reads {
|
|
1108
|
-
let namespace = if index % 2 == 0 {
|
|
1109
|
-
STORAGE_API_NAMESPACE
|
|
1110
|
-
} else {
|
|
1111
|
-
STORAGE_API_ALT_NAMESPACE
|
|
1112
|
-
};
|
|
1113
|
-
batch.put(namespace, storage_api_key(index), storage_api_value(index));
|
|
1114
|
-
}
|
|
1115
|
-
transaction.write_kv_batch(batch).await?;
|
|
1116
|
-
transaction.commit().await?;
|
|
1117
|
-
|
|
1118
|
-
let mut transaction = storage.begin_read_transaction().await?;
|
|
1119
|
-
let even_keys = (0..reads)
|
|
1120
|
-
.step_by(2)
|
|
1121
|
-
.map(storage_api_key)
|
|
1122
|
-
.collect::<Vec<_>>();
|
|
1123
|
-
let odd_keys = (1..reads)
|
|
1124
|
-
.step_by(2)
|
|
1125
|
-
.map(storage_api_key)
|
|
1126
|
-
.collect::<Vec<_>>();
|
|
1127
|
-
let started_at = Instant::now();
|
|
1128
|
-
let result = transaction
|
|
1129
|
-
.get_values(KvGetRequest {
|
|
1130
|
-
groups: vec![
|
|
1131
|
-
KvGetGroup {
|
|
1132
|
-
namespace: STORAGE_API_NAMESPACE.to_string(),
|
|
1133
|
-
keys: even_keys,
|
|
1134
|
-
},
|
|
1135
|
-
KvGetGroup {
|
|
1136
|
-
namespace: STORAGE_API_ALT_NAMESPACE.to_string(),
|
|
1137
|
-
keys: odd_keys,
|
|
1138
|
-
},
|
|
1139
|
-
],
|
|
1140
|
-
})
|
|
1141
|
-
.await?;
|
|
1142
|
-
transaction.rollback().await?;
|
|
1143
|
-
let verified_rows = result
|
|
1144
|
-
.groups
|
|
1145
|
-
.iter()
|
|
1146
|
-
.map(|group| group.values_iter().filter(|value| value.is_some()).count())
|
|
1147
|
-
.sum();
|
|
1148
|
-
Ok(StorageBenchReport {
|
|
1149
|
-
measured_rows: reads,
|
|
1150
|
-
verified_rows,
|
|
1151
|
-
elapsed: started_at.elapsed(),
|
|
1152
|
-
})
|
|
1153
|
-
}
|
|
1154
|
-
|
|
1155
|
-
pub async fn storage_api_get_values_duplicate_keys_prepared(
|
|
1156
|
-
fixture: &StorageApiFixture,
|
|
1157
|
-
reads: usize,
|
|
1158
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1159
|
-
let mut transaction = fixture.storage.begin_read_transaction().await?;
|
|
1160
|
-
let keys = (0..reads)
|
|
1161
|
-
.map(|index| storage_api_key(index % 100))
|
|
1162
|
-
.collect::<Vec<_>>();
|
|
1163
|
-
let started_at = Instant::now();
|
|
1164
|
-
let result = transaction
|
|
1165
|
-
.get_values(KvGetRequest {
|
|
1166
|
-
groups: vec![KvGetGroup {
|
|
1167
|
-
namespace: STORAGE_API_NAMESPACE.to_string(),
|
|
1168
|
-
keys,
|
|
1169
|
-
}],
|
|
1170
|
-
})
|
|
1171
|
-
.await?;
|
|
1172
|
-
transaction.rollback().await?;
|
|
1173
|
-
let verified_rows = result.groups[0]
|
|
1174
|
-
.values_iter()
|
|
1175
|
-
.filter(|value| value.is_some())
|
|
1176
|
-
.count();
|
|
1177
|
-
Ok(StorageBenchReport {
|
|
1178
|
-
measured_rows: reads,
|
|
1179
|
-
verified_rows,
|
|
1180
|
-
elapsed: started_at.elapsed(),
|
|
1181
|
-
})
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
pub async fn storage_api_scan_keys_prefix_prepared(
|
|
1185
|
-
fixture: &StorageApiFixture,
|
|
1186
|
-
limit: usize,
|
|
1187
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1188
|
-
let mut transaction = fixture.storage.begin_read_transaction().await?;
|
|
1189
|
-
let started_at = Instant::now();
|
|
1190
|
-
let result = transaction
|
|
1191
|
-
.scan_keys(KvScanRequest {
|
|
1192
|
-
namespace: STORAGE_API_NAMESPACE.to_string(),
|
|
1193
|
-
range: KvScanRange::prefix(b"key/".to_vec()),
|
|
1194
|
-
after: None,
|
|
1195
|
-
limit,
|
|
1196
|
-
})
|
|
1197
|
-
.await?;
|
|
1198
|
-
transaction.rollback().await?;
|
|
1199
|
-
Ok(StorageBenchReport {
|
|
1200
|
-
measured_rows: result.keys.len(),
|
|
1201
|
-
verified_rows: limit.min(fixture.rows),
|
|
1202
|
-
elapsed: started_at.elapsed(),
|
|
1203
|
-
})
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
|
-
pub async fn storage_api_scan_keys_after_pages_prepared(
|
|
1207
|
-
fixture: &StorageApiFixture,
|
|
1208
|
-
page_size: usize,
|
|
1209
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1210
|
-
let mut transaction = fixture.storage.begin_read_transaction().await?;
|
|
1211
|
-
let started_at = Instant::now();
|
|
1212
|
-
let mut after = None;
|
|
1213
|
-
let mut measured_rows = 0usize;
|
|
1214
|
-
loop {
|
|
1215
|
-
let result = transaction
|
|
1216
|
-
.scan_keys(KvScanRequest {
|
|
1217
|
-
namespace: STORAGE_API_NAMESPACE.to_string(),
|
|
1218
|
-
range: KvScanRange::prefix(b"key/".to_vec()),
|
|
1219
|
-
after,
|
|
1220
|
-
limit: page_size,
|
|
1221
|
-
})
|
|
1222
|
-
.await?;
|
|
1223
|
-
if result.keys.is_empty() {
|
|
1224
|
-
break;
|
|
1225
|
-
}
|
|
1226
|
-
measured_rows += result.keys.len();
|
|
1227
|
-
let Some(resume_after) = result.resume_after else {
|
|
1228
|
-
break;
|
|
1229
|
-
};
|
|
1230
|
-
after = Some(resume_after);
|
|
1231
|
-
}
|
|
1232
|
-
transaction.rollback().await?;
|
|
1233
|
-
Ok(StorageBenchReport {
|
|
1234
|
-
measured_rows,
|
|
1235
|
-
verified_rows: fixture.rows,
|
|
1236
|
-
elapsed: started_at.elapsed(),
|
|
1237
|
-
})
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
|
-
pub async fn storage_api_scan_keys_empty_range_prepared(
|
|
1241
|
-
fixture: &StorageApiFixture,
|
|
1242
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1243
|
-
let mut transaction = fixture.storage.begin_read_transaction().await?;
|
|
1244
|
-
let started_at = Instant::now();
|
|
1245
|
-
let result = transaction
|
|
1246
|
-
.scan_keys(KvScanRequest {
|
|
1247
|
-
namespace: STORAGE_API_NAMESPACE.to_string(),
|
|
1248
|
-
range: KvScanRange::prefix(b"absent/".to_vec()),
|
|
1249
|
-
after: None,
|
|
1250
|
-
limit: fixture.rows,
|
|
1251
|
-
})
|
|
1252
|
-
.await?;
|
|
1253
|
-
transaction.rollback().await?;
|
|
1254
|
-
Ok(StorageBenchReport {
|
|
1255
|
-
measured_rows: result.keys.len(),
|
|
1256
|
-
verified_rows: 0,
|
|
1257
|
-
elapsed: started_at.elapsed(),
|
|
1258
|
-
})
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
pub async fn prepare_storage_api_selective_scan(
|
|
1262
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
1263
|
-
rows: usize,
|
|
1264
|
-
selectivity: StorageBenchSelectivity,
|
|
1265
|
-
) -> Result<StorageApiFixture, LixError> {
|
|
1266
|
-
let storage = StorageContext::new(backend);
|
|
1267
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
1268
|
-
let mut batch = KvWriteBatch::new();
|
|
1269
|
-
for index in 0..rows {
|
|
1270
|
-
let key = if selectivity.matches(index) {
|
|
1271
|
-
storage_api_selective_key(index)
|
|
1272
|
-
} else {
|
|
1273
|
-
storage_api_key(index)
|
|
1274
|
-
};
|
|
1275
|
-
batch.put(STORAGE_API_NAMESPACE, key, storage_api_value(index));
|
|
1276
|
-
}
|
|
1277
|
-
transaction.write_kv_batch(batch).await?;
|
|
1278
|
-
transaction.commit().await?;
|
|
1279
|
-
Ok(StorageApiFixture { storage, rows })
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
pub async fn storage_api_scan_keys_selective_prefix_prepared(
|
|
1283
|
-
fixture: &StorageApiFixture,
|
|
1284
|
-
selectivity: StorageBenchSelectivity,
|
|
1285
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1286
|
-
let mut transaction = fixture.storage.begin_read_transaction().await?;
|
|
1287
|
-
let started_at = Instant::now();
|
|
1288
|
-
let result = transaction
|
|
1289
|
-
.scan_keys(KvScanRequest {
|
|
1290
|
-
namespace: STORAGE_API_NAMESPACE.to_string(),
|
|
1291
|
-
range: KvScanRange::prefix(b"selective/".to_vec()),
|
|
1292
|
-
after: None,
|
|
1293
|
-
limit: fixture.rows,
|
|
1294
|
-
})
|
|
1295
|
-
.await?;
|
|
1296
|
-
transaction.rollback().await?;
|
|
1297
|
-
Ok(StorageBenchReport {
|
|
1298
|
-
measured_rows: result.keys.len(),
|
|
1299
|
-
verified_rows: selectivity.expected_rows(fixture.rows),
|
|
1300
|
-
elapsed: started_at.elapsed(),
|
|
1301
|
-
})
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
pub async fn storage_api_transaction_commit_empty(
|
|
1305
|
-
backend: Arc<dyn Backend + Send + Sync>,
|
|
1306
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1307
|
-
let storage = StorageContext::new(backend);
|
|
1308
|
-
let started_at = Instant::now();
|
|
1309
|
-
let transaction = storage.begin_write_transaction().await?;
|
|
1310
|
-
transaction.commit().await?;
|
|
1311
|
-
Ok(StorageBenchReport {
|
|
1312
|
-
measured_rows: 0,
|
|
1313
|
-
verified_rows: 0,
|
|
1314
|
-
elapsed: started_at.elapsed(),
|
|
1315
|
-
})
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
fn storage_api_key(index: usize) -> Vec<u8> {
|
|
1319
|
-
format!("key/{index:08}").into_bytes()
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
|
-
fn storage_api_selective_key(index: usize) -> Vec<u8> {
|
|
1323
|
-
format!("selective/{index:08}").into_bytes()
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1326
|
-
fn storage_api_missing_key(index: usize) -> Vec<u8> {
|
|
1327
|
-
format!("missing/{index:08}").into_bytes()
|
|
1328
|
-
}
|
|
1329
|
-
|
|
1330
|
-
fn storage_api_value(index: usize) -> Vec<u8> {
|
|
1331
|
-
format!("value/{index:08}/{}", "x".repeat(64)).into_bytes()
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
|
-
fn storage_api_value_with_bytes(index: usize, value_bytes: usize) -> Vec<u8> {
|
|
1335
|
-
let prefix = format!("value/{index:08}/");
|
|
1336
|
-
if value_bytes <= prefix.len() {
|
|
1337
|
-
return prefix.into_bytes();
|
|
1338
|
-
}
|
|
1339
|
-
let mut value = prefix.into_bytes();
|
|
1340
|
-
value.extend(std::iter::repeat_n(b'x', value_bytes - value.len()));
|
|
1341
|
-
value
|
|
1342
|
-
}
|
|
1343
|
-
|
|
1344
|
-
fn storage_api_updated_value(index: usize) -> Vec<u8> {
|
|
1345
|
-
format!("updated/{index:08}/{}", "y".repeat(64)).into_bytes()
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
pub struct TrackedStateWriteRootFixture {
|
|
1349
|
-
context: TrackedStateContext,
|
|
1350
|
-
rows: Vec<MaterializedTrackedStateRow>,
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
pub struct TrackedStateReadFixture {
|
|
1354
|
-
context: TrackedStateContext,
|
|
1355
|
-
rows: usize,
|
|
1356
|
-
commit_id: String,
|
|
1357
|
-
key_pattern: StorageBenchKeyPattern,
|
|
1358
|
-
selectivity: StorageBenchSelectivity,
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1361
|
-
pub struct TrackedStateUpdateFixture {
|
|
1362
|
-
context: TrackedStateContext,
|
|
1363
|
-
rows: Vec<MaterializedTrackedStateRow>,
|
|
1364
|
-
}
|
|
1365
|
-
|
|
1366
|
-
pub struct TrackedStateDiffFixture {
|
|
1367
|
-
context: TrackedStateContext,
|
|
1368
|
-
left_commit_id: String,
|
|
1369
|
-
right_commit_id: String,
|
|
1370
|
-
expected_entries: usize,
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
pub struct TrackedStateMaterializeFixture {
|
|
1374
|
-
context: TrackedStateContext,
|
|
1375
|
-
commit_id: String,
|
|
1376
|
-
expected_rows: usize,
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
#[derive(Clone)]
|
|
1380
|
-
pub struct JsonPointerStorageRow {
|
|
1381
|
-
pub path: String,
|
|
1382
|
-
pub value_json: String,
|
|
1383
|
-
pub updated_value_json: String,
|
|
1384
|
-
}
|
|
1385
|
-
|
|
1386
|
-
pub struct JsonPointerTrackedStateReadFixture {
|
|
1387
|
-
context: TrackedStateContext,
|
|
1388
|
-
rows: Vec<JsonPointerStorageRow>,
|
|
1389
|
-
commit_id: String,
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
pub struct JsonPointerTrackedStateDiffFixture {
|
|
1393
|
-
context: TrackedStateContext,
|
|
1394
|
-
left_commit_id: String,
|
|
1395
|
-
right_commit_id: String,
|
|
1396
|
-
expected_entries: usize,
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
pub struct UntrackedStateWriteFixture {
|
|
1400
|
-
context: UntrackedStateContext,
|
|
1401
|
-
rows: Vec<MaterializedUntrackedStateRow>,
|
|
1402
|
-
}
|
|
1403
|
-
|
|
1404
|
-
pub struct UntrackedStateReadFixture {
|
|
1405
|
-
context: UntrackedStateContext,
|
|
1406
|
-
rows: usize,
|
|
1407
|
-
key_pattern: StorageBenchKeyPattern,
|
|
1408
|
-
selectivity: StorageBenchSelectivity,
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
pub struct ChangelogAppendFixture {
|
|
1412
|
-
context: CommitStoreContext,
|
|
1413
|
-
changes: Vec<MaterializedChange>,
|
|
1414
|
-
}
|
|
1415
|
-
|
|
1416
|
-
pub struct ChangelogReadFixture {
|
|
1417
|
-
context: CommitStoreContext,
|
|
1418
|
-
rows: usize,
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
|
-
pub struct ChangelogCodecFixture {
|
|
1422
|
-
changes: Vec<Change>,
|
|
1423
|
-
encoded_changes: Vec<Vec<u8>>,
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
pub struct CommitGraphReadFixture {
|
|
1427
|
-
head_commit_id: String,
|
|
1428
|
-
rows: usize,
|
|
1429
|
-
}
|
|
1430
|
-
|
|
1431
|
-
pub struct BinaryCasWriteFixture {
|
|
1432
|
-
context: BinaryCasContext,
|
|
1433
|
-
file_ids: Vec<String>,
|
|
1434
|
-
payloads: Vec<Vec<u8>>,
|
|
1435
|
-
}
|
|
1436
|
-
|
|
1437
|
-
pub struct BinaryCasReadFixture {
|
|
1438
|
-
context: BinaryCasContext,
|
|
1439
|
-
rows: usize,
|
|
1440
|
-
hashes: Vec<BlobHash>,
|
|
1441
|
-
}
|
|
1442
|
-
|
|
1443
|
-
#[derive(Debug, Clone, Copy)]
|
|
1444
|
-
pub enum JsonStorePayloadShape {
|
|
1445
|
-
SmallRaw1k,
|
|
1446
|
-
MediumStructured16k,
|
|
1447
|
-
LargeStructured128k,
|
|
1448
|
-
LargeArray128k,
|
|
1449
|
-
}
|
|
1450
|
-
|
|
1451
|
-
#[derive(Debug, Clone, Copy)]
|
|
1452
|
-
pub enum JsonStoreProjectionShape {
|
|
1453
|
-
TopLevelTarget,
|
|
1454
|
-
TopLevelTenProps,
|
|
1455
|
-
NestedTarget,
|
|
1456
|
-
ArrayItem999,
|
|
1457
|
-
Status,
|
|
1458
|
-
}
|
|
1459
|
-
|
|
1460
|
-
pub struct JsonStoreWriteFixture {
|
|
1461
|
-
context: JsonStoreContext,
|
|
1462
|
-
documents: Vec<Vec<u8>>,
|
|
1463
|
-
}
|
|
1464
|
-
|
|
1465
|
-
pub struct JsonStoreReadFixture {
|
|
1466
|
-
context: JsonStoreContext,
|
|
1467
|
-
refs: Vec<JsonRef>,
|
|
1468
|
-
paths: Vec<JsonProjectionPath>,
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
pub async fn prepare_tracked_state_write_root(
|
|
1472
|
-
config: StorageBenchConfig,
|
|
1473
|
-
) -> Result<TrackedStateWriteRootFixture, LixError> {
|
|
1474
|
-
Ok(TrackedStateWriteRootFixture {
|
|
1475
|
-
context: TrackedStateContext::new(),
|
|
1476
|
-
rows: tracked_rows(config, "bench-tracked-commit"),
|
|
1477
|
-
})
|
|
1478
|
-
}
|
|
1479
|
-
|
|
1480
|
-
pub async fn tracked_state_write_root_prepared(
|
|
1481
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1482
|
-
fixture: &TrackedStateWriteRootFixture,
|
|
1483
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1484
|
-
write_tracked_root(
|
|
1485
|
-
backend,
|
|
1486
|
-
&fixture.context,
|
|
1487
|
-
"bench-tracked-commit",
|
|
1488
|
-
None,
|
|
1489
|
-
&fixture.rows,
|
|
1490
|
-
)
|
|
1491
|
-
.await?;
|
|
1492
|
-
Ok(report(
|
|
1493
|
-
fixture.rows.len(),
|
|
1494
|
-
fixture.rows.len(),
|
|
1495
|
-
Duration::ZERO,
|
|
1496
|
-
))
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
pub async fn prepare_tracked_state_read(
|
|
1500
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1501
|
-
config: StorageBenchConfig,
|
|
1502
|
-
) -> Result<TrackedStateReadFixture, LixError> {
|
|
1503
|
-
let context = TrackedStateContext::new();
|
|
1504
|
-
let rows = tracked_rows(config, "bench-tracked-commit");
|
|
1505
|
-
write_tracked_root(backend, &context, "bench-tracked-commit", None, &rows).await?;
|
|
1506
|
-
Ok(TrackedStateReadFixture {
|
|
1507
|
-
context,
|
|
1508
|
-
rows: config.rows,
|
|
1509
|
-
commit_id: "bench-tracked-commit".to_string(),
|
|
1510
|
-
key_pattern: config.key_pattern,
|
|
1511
|
-
selectivity: config.selectivity,
|
|
1512
|
-
})
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
pub async fn prepare_tracked_state_read_file_selective(
|
|
1516
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1517
|
-
config: StorageBenchConfig,
|
|
1518
|
-
) -> Result<TrackedStateReadFixture, LixError> {
|
|
1519
|
-
let context = TrackedStateContext::new();
|
|
1520
|
-
let rows = tracked_rows_file_selective(config, "bench-tracked-commit");
|
|
1521
|
-
write_tracked_root(backend, &context, "bench-tracked-commit", None, &rows).await?;
|
|
1522
|
-
Ok(TrackedStateReadFixture {
|
|
1523
|
-
context,
|
|
1524
|
-
rows: config.rows,
|
|
1525
|
-
commit_id: "bench-tracked-commit".to_string(),
|
|
1526
|
-
key_pattern: config.key_pattern,
|
|
1527
|
-
selectivity: config.selectivity,
|
|
1528
|
-
})
|
|
1529
|
-
}
|
|
1530
|
-
|
|
1531
|
-
pub async fn prepare_tracked_state_read_after_update_rows(
|
|
1532
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1533
|
-
config: StorageBenchConfig,
|
|
1534
|
-
updated_rows: usize,
|
|
1535
|
-
) -> Result<TrackedStateReadFixture, LixError> {
|
|
1536
|
-
let fixture = prepare_tracked_state_update_rows(backend, config, updated_rows).await?;
|
|
1537
|
-
tracked_state_update_existing_prepared(backend, &fixture).await?;
|
|
1538
|
-
Ok(TrackedStateReadFixture {
|
|
1539
|
-
context: fixture.context,
|
|
1540
|
-
rows: config.rows,
|
|
1541
|
-
commit_id: "bench-tracked-child".to_string(),
|
|
1542
|
-
key_pattern: config.key_pattern,
|
|
1543
|
-
selectivity: config.selectivity,
|
|
1544
|
-
})
|
|
1545
|
-
}
|
|
1546
|
-
|
|
1547
|
-
pub async fn prepare_tracked_state_read_delta_chain(
|
|
1548
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1549
|
-
config: StorageBenchConfig,
|
|
1550
|
-
delta_commits: usize,
|
|
1551
|
-
updated_rows_per_commit: usize,
|
|
1552
|
-
) -> Result<TrackedStateReadFixture, LixError> {
|
|
1553
|
-
let (context, final_commit_id) =
|
|
1554
|
-
write_tracked_delta_chain(backend, config, delta_commits, updated_rows_per_commit).await?;
|
|
1555
|
-
Ok(TrackedStateReadFixture {
|
|
1556
|
-
context,
|
|
1557
|
-
rows: config.rows,
|
|
1558
|
-
commit_id: final_commit_id,
|
|
1559
|
-
key_pattern: config.key_pattern,
|
|
1560
|
-
selectivity: config.selectivity,
|
|
1561
|
-
})
|
|
1562
|
-
}
|
|
1563
|
-
|
|
1564
|
-
pub async fn prepare_tracked_state_read_materialized_delta_chain(
|
|
1565
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1566
|
-
config: StorageBenchConfig,
|
|
1567
|
-
delta_commits: usize,
|
|
1568
|
-
updated_rows_per_commit: usize,
|
|
1569
|
-
) -> Result<TrackedStateReadFixture, LixError> {
|
|
1570
|
-
let (context, final_commit_id) =
|
|
1571
|
-
write_tracked_delta_chain(backend, config, delta_commits, updated_rows_per_commit).await?;
|
|
1572
|
-
materialize_tracked_root(backend, &context, &final_commit_id).await?;
|
|
1573
|
-
Ok(TrackedStateReadFixture {
|
|
1574
|
-
context,
|
|
1575
|
-
rows: config.rows,
|
|
1576
|
-
commit_id: final_commit_id,
|
|
1577
|
-
key_pattern: config.key_pattern,
|
|
1578
|
-
selectivity: config.selectivity,
|
|
1579
|
-
})
|
|
1580
|
-
}
|
|
1581
|
-
|
|
1582
|
-
pub async fn prepare_tracked_state_materialize_delta_chain(
|
|
1583
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1584
|
-
config: StorageBenchConfig,
|
|
1585
|
-
delta_commits: usize,
|
|
1586
|
-
updated_rows_per_commit: usize,
|
|
1587
|
-
) -> Result<TrackedStateMaterializeFixture, LixError> {
|
|
1588
|
-
let (context, final_commit_id) =
|
|
1589
|
-
write_tracked_delta_chain(backend, config, delta_commits, updated_rows_per_commit).await?;
|
|
1590
|
-
Ok(TrackedStateMaterializeFixture {
|
|
1591
|
-
context,
|
|
1592
|
-
commit_id: final_commit_id,
|
|
1593
|
-
expected_rows: config.rows,
|
|
1594
|
-
})
|
|
1595
|
-
}
|
|
1596
|
-
|
|
1597
|
-
fn tracked_point_hit_requests(
|
|
1598
|
-
rows: usize,
|
|
1599
|
-
key_pattern: StorageBenchKeyPattern,
|
|
1600
|
-
) -> Vec<TrackedStateRowRequest> {
|
|
1601
|
-
(0..rows)
|
|
1602
|
-
.map(|index| TrackedStateRowRequest {
|
|
1603
|
-
schema_key: tracked_schema_key(index, StorageBenchSelectivity::Percent100),
|
|
1604
|
-
entity_id: EntityIdentity::single(entity_id("tracked", index, key_pattern)),
|
|
1605
|
-
file_id: NullableKeyFilter::Value("bench.json".to_string()),
|
|
1606
|
-
})
|
|
1607
|
-
.collect()
|
|
1608
|
-
}
|
|
1609
|
-
|
|
1610
|
-
fn tracked_point_miss_requests(
|
|
1611
|
-
rows: usize,
|
|
1612
|
-
selectivity: StorageBenchSelectivity,
|
|
1613
|
-
) -> Vec<TrackedStateRowRequest> {
|
|
1614
|
-
(0..rows)
|
|
1615
|
-
.map(|index| TrackedStateRowRequest {
|
|
1616
|
-
schema_key: tracked_schema_key(index, selectivity),
|
|
1617
|
-
entity_id: EntityIdentity::single(format!("missing-{index}")),
|
|
1618
|
-
file_id: NullableKeyFilter::Value("bench.json".to_string()),
|
|
1619
|
-
})
|
|
1620
|
-
.collect()
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
fn tracked_point_miss_requests_for_schema(
|
|
1624
|
-
rows: usize,
|
|
1625
|
-
schema_key: &str,
|
|
1626
|
-
) -> Vec<TrackedStateRowRequest> {
|
|
1627
|
-
(0..rows)
|
|
1628
|
-
.map(|index| TrackedStateRowRequest {
|
|
1629
|
-
schema_key: schema_key.to_string(),
|
|
1630
|
-
entity_id: EntityIdentity::single(format!("missing-{index}")),
|
|
1631
|
-
file_id: NullableKeyFilter::Value("bench.json".to_string()),
|
|
1632
|
-
})
|
|
1633
|
-
.collect()
|
|
1634
|
-
}
|
|
1635
|
-
|
|
1636
|
-
pub async fn tracked_state_read_point_hit_prepared(
|
|
1637
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1638
|
-
fixture: &TrackedStateReadFixture,
|
|
1639
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1640
|
-
let mut reader = fixture
|
|
1641
|
-
.context
|
|
1642
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
1643
|
-
let requests = tracked_point_hit_requests(fixture.rows, fixture.key_pattern);
|
|
1644
|
-
let verified_rows = reader
|
|
1645
|
-
.load_rows_at_commit(&fixture.commit_id, &requests)
|
|
1646
|
-
.await?
|
|
1647
|
-
.into_iter()
|
|
1648
|
-
.filter(Option::is_some)
|
|
1649
|
-
.count();
|
|
1650
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
1651
|
-
}
|
|
1652
|
-
|
|
1653
|
-
pub async fn tracked_state_read_point_hit_constant_prepared(
|
|
1654
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1655
|
-
fixture: &TrackedStateReadFixture,
|
|
1656
|
-
measured_reads: usize,
|
|
1657
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1658
|
-
let measured_rows = measured_reads.min(fixture.rows);
|
|
1659
|
-
let mut reader = fixture
|
|
1660
|
-
.context
|
|
1661
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
1662
|
-
let requests = tracked_point_hit_requests(measured_rows, fixture.key_pattern);
|
|
1663
|
-
let verified_rows = reader
|
|
1664
|
-
.load_rows_at_commit(&fixture.commit_id, &requests)
|
|
1665
|
-
.await?
|
|
1666
|
-
.into_iter()
|
|
1667
|
-
.filter(Option::is_some)
|
|
1668
|
-
.count();
|
|
1669
|
-
Ok(report(measured_rows, verified_rows, Duration::ZERO))
|
|
1670
|
-
}
|
|
1671
|
-
|
|
1672
|
-
pub async fn tracked_state_read_point_miss_prepared(
|
|
1673
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1674
|
-
fixture: &TrackedStateReadFixture,
|
|
1675
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1676
|
-
let mut reader = fixture
|
|
1677
|
-
.context
|
|
1678
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
1679
|
-
let requests = tracked_point_miss_requests_for_schema(fixture.rows, TRACKED_MATCH_SCHEMA_KEY);
|
|
1680
|
-
let misses = reader
|
|
1681
|
-
.load_rows_at_commit(&fixture.commit_id, &requests)
|
|
1682
|
-
.await?
|
|
1683
|
-
.into_iter()
|
|
1684
|
-
.filter(Option::is_none)
|
|
1685
|
-
.count();
|
|
1686
|
-
Ok(report(fixture.rows, misses, Duration::ZERO))
|
|
1687
|
-
}
|
|
1688
|
-
|
|
1689
|
-
pub async fn tracked_state_scan_all_prepared(
|
|
1690
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1691
|
-
fixture: &TrackedStateReadFixture,
|
|
1692
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1693
|
-
let verified_rows = scan_tracked(backend, &fixture.context, &fixture.commit_id)
|
|
1694
|
-
.await?
|
|
1695
|
-
.len();
|
|
1696
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
1697
|
-
}
|
|
1698
|
-
|
|
1699
|
-
pub async fn tracked_state_scan_keys_only_prepared(
|
|
1700
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1701
|
-
fixture: &TrackedStateReadFixture,
|
|
1702
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1703
|
-
let mut reader = fixture
|
|
1704
|
-
.context
|
|
1705
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
1706
|
-
let verified_rows = reader
|
|
1707
|
-
.scan_rows_at_commit(
|
|
1708
|
-
&fixture.commit_id,
|
|
1709
|
-
&TrackedStateScanRequest {
|
|
1710
|
-
projection: TrackedStateProjection {
|
|
1711
|
-
columns: vec!["entity_id".to_string()],
|
|
1712
|
-
},
|
|
1713
|
-
..Default::default()
|
|
1714
|
-
},
|
|
1715
|
-
)
|
|
1716
|
-
.await?
|
|
1717
|
-
.len();
|
|
1718
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
1719
|
-
}
|
|
1720
|
-
|
|
1721
|
-
pub async fn tracked_state_scan_headers_only_prepared(
|
|
1722
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1723
|
-
fixture: &TrackedStateReadFixture,
|
|
1724
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1725
|
-
let mut reader = fixture
|
|
1726
|
-
.context
|
|
1727
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
1728
|
-
let verified_rows = reader
|
|
1729
|
-
.scan_rows_at_commit(
|
|
1730
|
-
&fixture.commit_id,
|
|
1731
|
-
&TrackedStateScanRequest {
|
|
1732
|
-
projection: TrackedStateProjection {
|
|
1733
|
-
columns: tracked_state_header_columns(),
|
|
1734
|
-
},
|
|
1735
|
-
..Default::default()
|
|
1736
|
-
},
|
|
1737
|
-
)
|
|
1738
|
-
.await?
|
|
1739
|
-
.len();
|
|
1740
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
1741
|
-
}
|
|
1742
|
-
|
|
1743
|
-
pub async fn tracked_state_scan_full_rows_prepared(
|
|
1744
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1745
|
-
fixture: &TrackedStateReadFixture,
|
|
1746
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1747
|
-
tracked_state_scan_all_prepared(backend, fixture).await
|
|
1748
|
-
}
|
|
1749
|
-
|
|
1750
|
-
pub async fn tracked_state_scan_schema_prepared(
|
|
1751
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1752
|
-
fixture: &TrackedStateReadFixture,
|
|
1753
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1754
|
-
let mut reader = fixture
|
|
1755
|
-
.context
|
|
1756
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
1757
|
-
let verified_rows = reader
|
|
1758
|
-
.scan_rows_at_commit(
|
|
1759
|
-
&fixture.commit_id,
|
|
1760
|
-
&TrackedStateScanRequest {
|
|
1761
|
-
filter: TrackedStateFilter {
|
|
1762
|
-
schema_keys: vec![tracked_schema_key(0, StorageBenchSelectivity::Percent100)],
|
|
1763
|
-
..Default::default()
|
|
1764
|
-
},
|
|
1765
|
-
..Default::default()
|
|
1766
|
-
},
|
|
1767
|
-
)
|
|
1768
|
-
.await?
|
|
1769
|
-
.len();
|
|
1770
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
1771
|
-
}
|
|
1772
|
-
|
|
1773
|
-
pub async fn tracked_state_scan_schema_selective_prepared(
|
|
1774
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1775
|
-
fixture: &TrackedStateReadFixture,
|
|
1776
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1777
|
-
let mut reader = fixture
|
|
1778
|
-
.context
|
|
1779
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
1780
|
-
let verified_rows = reader
|
|
1781
|
-
.scan_rows_at_commit(
|
|
1782
|
-
&fixture.commit_id,
|
|
1783
|
-
&TrackedStateScanRequest {
|
|
1784
|
-
filter: TrackedStateFilter {
|
|
1785
|
-
schema_keys: vec![TRACKED_MATCH_SCHEMA_KEY.to_string()],
|
|
1786
|
-
..Default::default()
|
|
1787
|
-
},
|
|
1788
|
-
..Default::default()
|
|
1789
|
-
},
|
|
1790
|
-
)
|
|
1791
|
-
.await?
|
|
1792
|
-
.len();
|
|
1793
|
-
Ok(report(
|
|
1794
|
-
fixture.selectivity.expected_rows(fixture.rows),
|
|
1795
|
-
verified_rows,
|
|
1796
|
-
Duration::ZERO,
|
|
1797
|
-
))
|
|
1798
|
-
}
|
|
1799
|
-
|
|
1800
|
-
pub async fn tracked_state_scan_file_prepared(
|
|
1801
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1802
|
-
fixture: &TrackedStateReadFixture,
|
|
1803
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1804
|
-
let mut reader = fixture
|
|
1805
|
-
.context
|
|
1806
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
1807
|
-
let verified_rows = reader
|
|
1808
|
-
.scan_rows_at_commit(
|
|
1809
|
-
&fixture.commit_id,
|
|
1810
|
-
&TrackedStateScanRequest {
|
|
1811
|
-
filter: TrackedStateFilter {
|
|
1812
|
-
file_ids: vec![NullableKeyFilter::Value("bench.json".to_string())],
|
|
1813
|
-
..Default::default()
|
|
1814
|
-
},
|
|
1815
|
-
..Default::default()
|
|
1816
|
-
},
|
|
1817
|
-
)
|
|
1818
|
-
.await?
|
|
1819
|
-
.len();
|
|
1820
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
1821
|
-
}
|
|
1822
|
-
|
|
1823
|
-
pub async fn tracked_state_scan_file_selective_prepared(
|
|
1824
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1825
|
-
fixture: &TrackedStateReadFixture,
|
|
1826
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1827
|
-
let mut reader = fixture
|
|
1828
|
-
.context
|
|
1829
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
1830
|
-
let verified_rows = reader
|
|
1831
|
-
.scan_rows_at_commit(
|
|
1832
|
-
&fixture.commit_id,
|
|
1833
|
-
&TrackedStateScanRequest {
|
|
1834
|
-
filter: TrackedStateFilter {
|
|
1835
|
-
file_ids: vec![NullableKeyFilter::Value("bench-match.json".to_string())],
|
|
1836
|
-
..Default::default()
|
|
1837
|
-
},
|
|
1838
|
-
..Default::default()
|
|
1839
|
-
},
|
|
1840
|
-
)
|
|
1841
|
-
.await?
|
|
1842
|
-
.len();
|
|
1843
|
-
Ok(report(
|
|
1844
|
-
fixture.selectivity.expected_rows(fixture.rows),
|
|
1845
|
-
verified_rows,
|
|
1846
|
-
Duration::ZERO,
|
|
1847
|
-
))
|
|
1848
|
-
}
|
|
1849
|
-
|
|
1850
|
-
pub async fn tracked_state_scan_file_header_selective_prepared(
|
|
1851
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1852
|
-
fixture: &TrackedStateReadFixture,
|
|
1853
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1854
|
-
let mut reader = fixture
|
|
1855
|
-
.context
|
|
1856
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
1857
|
-
let verified_rows = reader
|
|
1858
|
-
.scan_rows_at_commit(
|
|
1859
|
-
&fixture.commit_id,
|
|
1860
|
-
&TrackedStateScanRequest {
|
|
1861
|
-
filter: TrackedStateFilter {
|
|
1862
|
-
file_ids: vec![NullableKeyFilter::Value("bench-match.json".to_string())],
|
|
1863
|
-
..Default::default()
|
|
1864
|
-
},
|
|
1865
|
-
projection: TrackedStateProjection {
|
|
1866
|
-
columns: tracked_state_header_columns(),
|
|
1867
|
-
},
|
|
1868
|
-
..Default::default()
|
|
1869
|
-
},
|
|
1870
|
-
)
|
|
1871
|
-
.await?
|
|
1872
|
-
.len();
|
|
1873
|
-
Ok(report(
|
|
1874
|
-
fixture.selectivity.expected_rows(fixture.rows),
|
|
1875
|
-
verified_rows,
|
|
1876
|
-
Duration::ZERO,
|
|
1877
|
-
))
|
|
1878
|
-
}
|
|
1879
|
-
|
|
1880
|
-
pub async fn prepare_tracked_state_update(
|
|
1881
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1882
|
-
config: StorageBenchConfig,
|
|
1883
|
-
) -> Result<TrackedStateUpdateFixture, LixError> {
|
|
1884
|
-
prepare_tracked_state_update_rows(backend, config, config.update_fraction.rows(config.rows))
|
|
1885
|
-
.await
|
|
1886
|
-
}
|
|
1887
|
-
|
|
1888
|
-
pub async fn prepare_tracked_state_update_rows(
|
|
1889
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1890
|
-
config: StorageBenchConfig,
|
|
1891
|
-
updated_rows: usize,
|
|
1892
|
-
) -> Result<TrackedStateUpdateFixture, LixError> {
|
|
1893
|
-
let context = TrackedStateContext::new();
|
|
1894
|
-
let rows = tracked_rows(config, "bench-tracked-parent");
|
|
1895
|
-
write_tracked_root(backend, &context, "bench-tracked-parent", None, &rows).await?;
|
|
1896
|
-
let mut updated_rows = tracked_rows(
|
|
1897
|
-
config.with_rows(updated_rows.min(config.rows)),
|
|
1898
|
-
"bench-tracked-child",
|
|
1899
|
-
);
|
|
1900
|
-
for (index, row) in updated_rows.iter_mut().enumerate() {
|
|
1901
|
-
row.snapshot_content = Some(updated_snapshot_content(index, config.state_payload_bytes));
|
|
1902
|
-
}
|
|
1903
|
-
Ok(TrackedStateUpdateFixture {
|
|
1904
|
-
context,
|
|
1905
|
-
rows: updated_rows,
|
|
1906
|
-
})
|
|
1907
|
-
}
|
|
1908
|
-
|
|
1909
|
-
pub async fn prepare_tracked_state_partial_snapshot_update_rows(
|
|
1910
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1911
|
-
config: StorageBenchConfig,
|
|
1912
|
-
updated_rows: usize,
|
|
1913
|
-
) -> Result<TrackedStateUpdateFixture, LixError> {
|
|
1914
|
-
let context = TrackedStateContext::new();
|
|
1915
|
-
let rows = tracked_rows(config, "bench-tracked-parent");
|
|
1916
|
-
write_tracked_root(backend, &context, "bench-tracked-parent", None, &rows).await?;
|
|
1917
|
-
let mut updated_rows = tracked_rows(
|
|
1918
|
-
config.with_rows(updated_rows.min(config.rows)),
|
|
1919
|
-
"bench-tracked-child",
|
|
1920
|
-
);
|
|
1921
|
-
for (index, row) in updated_rows.iter_mut().enumerate() {
|
|
1922
|
-
row.snapshot_content = Some(partial_updated_snapshot_content(
|
|
1923
|
-
index,
|
|
1924
|
-
config.state_payload_bytes,
|
|
1925
|
-
));
|
|
1926
|
-
}
|
|
1927
|
-
Ok(TrackedStateUpdateFixture {
|
|
1928
|
-
context,
|
|
1929
|
-
rows: updated_rows,
|
|
1930
|
-
})
|
|
1931
|
-
}
|
|
1932
|
-
|
|
1933
|
-
pub async fn prepare_tracked_state_append_child(
|
|
1934
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1935
|
-
config: StorageBenchConfig,
|
|
1936
|
-
) -> Result<TrackedStateUpdateFixture, LixError> {
|
|
1937
|
-
prepare_tracked_state_append_child_rows(backend, config, config.rows).await
|
|
1938
|
-
}
|
|
1939
|
-
|
|
1940
|
-
pub async fn prepare_tracked_state_append_child_rows(
|
|
1941
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1942
|
-
config: StorageBenchConfig,
|
|
1943
|
-
appended_rows: usize,
|
|
1944
|
-
) -> Result<TrackedStateUpdateFixture, LixError> {
|
|
1945
|
-
let context = TrackedStateContext::new();
|
|
1946
|
-
let rows = tracked_rows(config, "bench-tracked-parent");
|
|
1947
|
-
write_tracked_root(backend, &context, "bench-tracked-parent", None, &rows).await?;
|
|
1948
|
-
let mut appended_rows = tracked_rows(
|
|
1949
|
-
config.with_rows(appended_rows.min(config.rows)),
|
|
1950
|
-
"bench-tracked-child",
|
|
1951
|
-
);
|
|
1952
|
-
for (index, row) in appended_rows.iter_mut().enumerate() {
|
|
1953
|
-
row.entity_id = EntityIdentity::single(entity_id("tracked-new", index, config.key_pattern));
|
|
1954
|
-
row.change_id = format!("tracked-new-change-{index}");
|
|
1955
|
-
}
|
|
1956
|
-
Ok(TrackedStateUpdateFixture {
|
|
1957
|
-
context,
|
|
1958
|
-
rows: appended_rows,
|
|
1959
|
-
})
|
|
1960
|
-
}
|
|
1961
|
-
|
|
1962
|
-
pub async fn prepare_tracked_state_tombstone_rows(
|
|
1963
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1964
|
-
config: StorageBenchConfig,
|
|
1965
|
-
tombstone_rows: usize,
|
|
1966
|
-
) -> Result<TrackedStateUpdateFixture, LixError> {
|
|
1967
|
-
let context = TrackedStateContext::new();
|
|
1968
|
-
let rows = tracked_rows(config, "bench-tracked-parent");
|
|
1969
|
-
write_tracked_root(backend, &context, "bench-tracked-parent", None, &rows).await?;
|
|
1970
|
-
let mut tombstones = tracked_rows(
|
|
1971
|
-
config.with_rows(tombstone_rows.min(config.rows)),
|
|
1972
|
-
"bench-tracked-child",
|
|
1973
|
-
);
|
|
1974
|
-
for row in &mut tombstones {
|
|
1975
|
-
row.snapshot_content = None;
|
|
1976
|
-
}
|
|
1977
|
-
Ok(TrackedStateUpdateFixture {
|
|
1978
|
-
context,
|
|
1979
|
-
rows: tombstones,
|
|
1980
|
-
})
|
|
1981
|
-
}
|
|
1982
|
-
|
|
1983
|
-
pub async fn tracked_state_update_existing_prepared(
|
|
1984
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
1985
|
-
fixture: &TrackedStateUpdateFixture,
|
|
1986
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
1987
|
-
write_tracked_root(
|
|
1988
|
-
backend,
|
|
1989
|
-
&fixture.context,
|
|
1990
|
-
"bench-tracked-child",
|
|
1991
|
-
Some("bench-tracked-parent"),
|
|
1992
|
-
&fixture.rows,
|
|
1993
|
-
)
|
|
1994
|
-
.await?;
|
|
1995
|
-
Ok(report(
|
|
1996
|
-
fixture.rows.len(),
|
|
1997
|
-
fixture.rows.len(),
|
|
1998
|
-
Duration::ZERO,
|
|
1999
|
-
))
|
|
2000
|
-
}
|
|
2001
|
-
|
|
2002
|
-
pub async fn prepare_tracked_state_diff_update_rows(
|
|
2003
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2004
|
-
config: StorageBenchConfig,
|
|
2005
|
-
updated_rows: usize,
|
|
2006
|
-
) -> Result<TrackedStateDiffFixture, LixError> {
|
|
2007
|
-
let fixture = prepare_tracked_state_update_rows(backend, config, updated_rows).await?;
|
|
2008
|
-
tracked_state_update_existing_prepared(backend, &fixture).await?;
|
|
2009
|
-
Ok(TrackedStateDiffFixture {
|
|
2010
|
-
context: fixture.context,
|
|
2011
|
-
left_commit_id: "bench-tracked-parent".to_string(),
|
|
2012
|
-
right_commit_id: "bench-tracked-child".to_string(),
|
|
2013
|
-
expected_entries: fixture.rows.len(),
|
|
2014
|
-
})
|
|
2015
|
-
}
|
|
2016
|
-
|
|
2017
|
-
pub async fn prepare_tracked_state_diff_delta_chain(
|
|
2018
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2019
|
-
config: StorageBenchConfig,
|
|
2020
|
-
delta_commits: usize,
|
|
2021
|
-
updated_rows_per_commit: usize,
|
|
2022
|
-
) -> Result<TrackedStateDiffFixture, LixError> {
|
|
2023
|
-
let (context, final_commit_id) =
|
|
2024
|
-
write_tracked_delta_chain(backend, config, delta_commits, updated_rows_per_commit).await?;
|
|
2025
|
-
Ok(TrackedStateDiffFixture {
|
|
2026
|
-
context,
|
|
2027
|
-
left_commit_id: "bench-tracked-base".to_string(),
|
|
2028
|
-
right_commit_id: final_commit_id,
|
|
2029
|
-
expected_entries: updated_rows_per_commit.min(config.rows),
|
|
2030
|
-
})
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
pub async fn prepare_tracked_state_diff_tombstone_rows(
|
|
2034
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2035
|
-
config: StorageBenchConfig,
|
|
2036
|
-
tombstone_rows: usize,
|
|
2037
|
-
) -> Result<TrackedStateDiffFixture, LixError> {
|
|
2038
|
-
let fixture = prepare_tracked_state_tombstone_rows(backend, config, tombstone_rows).await?;
|
|
2039
|
-
tracked_state_update_existing_prepared(backend, &fixture).await?;
|
|
2040
|
-
Ok(TrackedStateDiffFixture {
|
|
2041
|
-
context: fixture.context,
|
|
2042
|
-
left_commit_id: "bench-tracked-parent".to_string(),
|
|
2043
|
-
right_commit_id: "bench-tracked-child".to_string(),
|
|
2044
|
-
expected_entries: fixture.rows.len(),
|
|
2045
|
-
})
|
|
2046
|
-
}
|
|
2047
|
-
|
|
2048
|
-
pub async fn prepare_tracked_state_diff_equal(
|
|
2049
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2050
|
-
config: StorageBenchConfig,
|
|
2051
|
-
) -> Result<TrackedStateDiffFixture, LixError> {
|
|
2052
|
-
let context = TrackedStateContext::new();
|
|
2053
|
-
let rows = tracked_rows(config, "bench-tracked-parent");
|
|
2054
|
-
write_tracked_root(backend, &context, "bench-tracked-parent", None, &rows).await?;
|
|
2055
|
-
Ok(TrackedStateDiffFixture {
|
|
2056
|
-
context,
|
|
2057
|
-
left_commit_id: "bench-tracked-parent".to_string(),
|
|
2058
|
-
right_commit_id: "bench-tracked-parent".to_string(),
|
|
2059
|
-
expected_entries: 0,
|
|
2060
|
-
})
|
|
2061
|
-
}
|
|
2062
|
-
|
|
2063
|
-
pub async fn tracked_state_diff_commits_prepared(
|
|
2064
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2065
|
-
fixture: &TrackedStateDiffFixture,
|
|
2066
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2067
|
-
let mut reader = fixture
|
|
2068
|
-
.context
|
|
2069
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2070
|
-
let diff = reader
|
|
2071
|
-
.diff_commits(
|
|
2072
|
-
&fixture.left_commit_id,
|
|
2073
|
-
&fixture.right_commit_id,
|
|
2074
|
-
&TrackedStateDiffRequest::default(),
|
|
2075
|
-
)
|
|
2076
|
-
.await?;
|
|
2077
|
-
Ok(report(
|
|
2078
|
-
fixture.expected_entries,
|
|
2079
|
-
diff.entries.len(),
|
|
2080
|
-
Duration::ZERO,
|
|
2081
|
-
))
|
|
2082
|
-
}
|
|
2083
|
-
|
|
2084
|
-
pub async fn tracked_state_materialize_root_prepared(
|
|
2085
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2086
|
-
fixture: &TrackedStateMaterializeFixture,
|
|
2087
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2088
|
-
materialize_tracked_root(backend, &fixture.context, &fixture.commit_id).await?;
|
|
2089
|
-
Ok(report(
|
|
2090
|
-
fixture.expected_rows,
|
|
2091
|
-
fixture.expected_rows,
|
|
2092
|
-
Duration::ZERO,
|
|
2093
|
-
))
|
|
2094
|
-
}
|
|
2095
|
-
|
|
2096
|
-
pub async fn prepare_json_pointer_tracked_state_write_root(
|
|
2097
|
-
rows: &[JsonPointerStorageRow],
|
|
2098
|
-
) -> Result<TrackedStateWriteRootFixture, LixError> {
|
|
2099
|
-
Ok(TrackedStateWriteRootFixture {
|
|
2100
|
-
context: TrackedStateContext::new(),
|
|
2101
|
-
rows: json_pointer_tracked_rows(rows, "json-pointer-base", false),
|
|
2102
|
-
})
|
|
2103
|
-
}
|
|
2104
|
-
|
|
2105
|
-
pub async fn prepare_json_pointer_tracked_state_read(
|
|
2106
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2107
|
-
rows: &[JsonPointerStorageRow],
|
|
2108
|
-
) -> Result<JsonPointerTrackedStateReadFixture, LixError> {
|
|
2109
|
-
let context = TrackedStateContext::new();
|
|
2110
|
-
let materialized_rows = json_pointer_tracked_rows(rows, "json-pointer-base", false);
|
|
2111
|
-
write_tracked_root(
|
|
2112
|
-
backend,
|
|
2113
|
-
&context,
|
|
2114
|
-
"json-pointer-base",
|
|
2115
|
-
None,
|
|
2116
|
-
&materialized_rows,
|
|
2117
|
-
)
|
|
2118
|
-
.await?;
|
|
2119
|
-
Ok(JsonPointerTrackedStateReadFixture {
|
|
2120
|
-
context,
|
|
2121
|
-
rows: rows.to_vec(),
|
|
2122
|
-
commit_id: "json-pointer-base".to_string(),
|
|
2123
|
-
})
|
|
2124
|
-
}
|
|
2125
|
-
|
|
2126
|
-
pub async fn prepare_json_pointer_tracked_state_diff_update_rows(
|
|
2127
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2128
|
-
rows: &[JsonPointerStorageRow],
|
|
2129
|
-
updated_rows: usize,
|
|
2130
|
-
) -> Result<JsonPointerTrackedStateDiffFixture, LixError> {
|
|
2131
|
-
let context = TrackedStateContext::new();
|
|
2132
|
-
let base_rows = json_pointer_tracked_rows(rows, "json-pointer-base", false);
|
|
2133
|
-
write_tracked_root(backend, &context, "json-pointer-base", None, &base_rows).await?;
|
|
2134
|
-
let child_rows = json_pointer_tracked_rows(
|
|
2135
|
-
&rows[..updated_rows.min(rows.len())],
|
|
2136
|
-
"json-pointer-child",
|
|
2137
|
-
true,
|
|
2138
|
-
);
|
|
2139
|
-
write_tracked_root(
|
|
2140
|
-
backend,
|
|
2141
|
-
&context,
|
|
2142
|
-
"json-pointer-child",
|
|
2143
|
-
Some("json-pointer-base"),
|
|
2144
|
-
&child_rows,
|
|
2145
|
-
)
|
|
2146
|
-
.await?;
|
|
2147
|
-
Ok(JsonPointerTrackedStateDiffFixture {
|
|
2148
|
-
context,
|
|
2149
|
-
left_commit_id: "json-pointer-base".to_string(),
|
|
2150
|
-
right_commit_id: "json-pointer-child".to_string(),
|
|
2151
|
-
expected_entries: child_rows.len(),
|
|
2152
|
-
})
|
|
2153
|
-
}
|
|
2154
|
-
|
|
2155
|
-
pub async fn json_pointer_tracked_state_get_many_prepared(
|
|
2156
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2157
|
-
fixture: &JsonPointerTrackedStateReadFixture,
|
|
2158
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2159
|
-
let mut reader = fixture
|
|
2160
|
-
.context
|
|
2161
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2162
|
-
let requests = fixture
|
|
2163
|
-
.rows
|
|
2164
|
-
.iter()
|
|
2165
|
-
.map(|row| TrackedStateRowRequest {
|
|
2166
|
-
schema_key: "json_pointer".to_string(),
|
|
2167
|
-
entity_id: EntityIdentity::single(row.path.as_str()),
|
|
2168
|
-
file_id: NullableKeyFilter::Null,
|
|
2169
|
-
})
|
|
2170
|
-
.collect::<Vec<_>>();
|
|
2171
|
-
let verified_rows = reader
|
|
2172
|
-
.load_rows_at_commit(&fixture.commit_id, &requests)
|
|
2173
|
-
.await?
|
|
2174
|
-
.into_iter()
|
|
2175
|
-
.filter(Option::is_some)
|
|
2176
|
-
.count();
|
|
2177
|
-
Ok(report(fixture.rows.len(), verified_rows, Duration::ZERO))
|
|
2178
|
-
}
|
|
2179
|
-
|
|
2180
|
-
pub async fn json_pointer_tracked_state_get_many_missing_prepared(
|
|
2181
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2182
|
-
fixture: &JsonPointerTrackedStateReadFixture,
|
|
2183
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2184
|
-
let mut reader = fixture
|
|
2185
|
-
.context
|
|
2186
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2187
|
-
let requests = fixture
|
|
2188
|
-
.rows
|
|
2189
|
-
.iter()
|
|
2190
|
-
.map(|row| TrackedStateRowRequest {
|
|
2191
|
-
schema_key: "json_pointer".to_string(),
|
|
2192
|
-
entity_id: EntityIdentity::single(format!("missing{}", row.path)),
|
|
2193
|
-
file_id: NullableKeyFilter::Null,
|
|
2194
|
-
})
|
|
2195
|
-
.collect::<Vec<_>>();
|
|
2196
|
-
let verified_rows = reader
|
|
2197
|
-
.load_rows_at_commit(&fixture.commit_id, &requests)
|
|
2198
|
-
.await?
|
|
2199
|
-
.into_iter()
|
|
2200
|
-
.filter(Option::is_none)
|
|
2201
|
-
.count();
|
|
2202
|
-
Ok(report(fixture.rows.len(), verified_rows, Duration::ZERO))
|
|
2203
|
-
}
|
|
2204
|
-
|
|
2205
|
-
pub async fn json_pointer_tracked_state_scan_keys_only_prepared(
|
|
2206
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2207
|
-
fixture: &JsonPointerTrackedStateReadFixture,
|
|
2208
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2209
|
-
json_pointer_scan_with_projection(
|
|
2210
|
-
backend,
|
|
2211
|
-
fixture,
|
|
2212
|
-
TrackedStateProjection {
|
|
2213
|
-
columns: vec!["entity_id".to_string()],
|
|
2214
|
-
},
|
|
2215
|
-
)
|
|
2216
|
-
.await
|
|
2217
|
-
}
|
|
2218
|
-
|
|
2219
|
-
pub async fn json_pointer_tracked_state_scan_headers_only_prepared(
|
|
2220
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2221
|
-
fixture: &JsonPointerTrackedStateReadFixture,
|
|
2222
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2223
|
-
json_pointer_scan_with_projection(
|
|
2224
|
-
backend,
|
|
2225
|
-
fixture,
|
|
2226
|
-
TrackedStateProjection {
|
|
2227
|
-
columns: tracked_state_header_columns(),
|
|
2228
|
-
},
|
|
2229
|
-
)
|
|
2230
|
-
.await
|
|
2231
|
-
}
|
|
2232
|
-
|
|
2233
|
-
pub async fn json_pointer_tracked_state_scan_full_rows_prepared(
|
|
2234
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2235
|
-
fixture: &JsonPointerTrackedStateReadFixture,
|
|
2236
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2237
|
-
json_pointer_scan_with_projection(backend, fixture, TrackedStateProjection::default()).await
|
|
2238
|
-
}
|
|
2239
|
-
|
|
2240
|
-
pub async fn json_pointer_tracked_state_prefix_scan_schema_prepared(
|
|
2241
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2242
|
-
fixture: &JsonPointerTrackedStateReadFixture,
|
|
2243
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2244
|
-
json_pointer_scan_with_projection(backend, fixture, TrackedStateProjection::default()).await
|
|
2245
|
-
}
|
|
2246
|
-
|
|
2247
|
-
pub async fn json_pointer_tracked_state_prefix_scan_schema_file_null_prepared(
|
|
2248
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2249
|
-
fixture: &JsonPointerTrackedStateReadFixture,
|
|
2250
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2251
|
-
json_pointer_scan_with_projection(backend, fixture, TrackedStateProjection::default()).await
|
|
2252
|
-
}
|
|
2253
|
-
|
|
2254
|
-
async fn json_pointer_scan_with_projection(
|
|
2255
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2256
|
-
fixture: &JsonPointerTrackedStateReadFixture,
|
|
2257
|
-
projection: TrackedStateProjection,
|
|
2258
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2259
|
-
let mut reader = fixture
|
|
2260
|
-
.context
|
|
2261
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2262
|
-
let verified_rows = reader
|
|
2263
|
-
.scan_rows_at_commit(
|
|
2264
|
-
&fixture.commit_id,
|
|
2265
|
-
&TrackedStateScanRequest {
|
|
2266
|
-
filter: TrackedStateFilter {
|
|
2267
|
-
schema_keys: vec!["json_pointer".to_string()],
|
|
2268
|
-
file_ids: vec![NullableKeyFilter::Null],
|
|
2269
|
-
..Default::default()
|
|
2270
|
-
},
|
|
2271
|
-
projection,
|
|
2272
|
-
..Default::default()
|
|
2273
|
-
},
|
|
2274
|
-
)
|
|
2275
|
-
.await?
|
|
2276
|
-
.len();
|
|
2277
|
-
Ok(report(fixture.rows.len(), verified_rows, Duration::ZERO))
|
|
2278
|
-
}
|
|
2279
|
-
|
|
2280
|
-
pub async fn prepare_json_pointer_tracked_state_update_rows(
|
|
2281
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2282
|
-
rows: &[JsonPointerStorageRow],
|
|
2283
|
-
updated_rows: usize,
|
|
2284
|
-
) -> Result<TrackedStateUpdateFixture, LixError> {
|
|
2285
|
-
let context = TrackedStateContext::new();
|
|
2286
|
-
let base_rows = json_pointer_tracked_rows(rows, "json-pointer-base", false);
|
|
2287
|
-
write_tracked_root(backend, &context, "json-pointer-base", None, &base_rows).await?;
|
|
2288
|
-
let child_rows = json_pointer_tracked_rows(
|
|
2289
|
-
&rows[..updated_rows.min(rows.len())],
|
|
2290
|
-
"json-pointer-child",
|
|
2291
|
-
true,
|
|
2292
|
-
);
|
|
2293
|
-
Ok(TrackedStateUpdateFixture {
|
|
2294
|
-
context,
|
|
2295
|
-
rows: child_rows,
|
|
2296
|
-
})
|
|
2297
|
-
}
|
|
2298
|
-
|
|
2299
|
-
pub async fn prepare_json_pointer_tracked_state_tombstone_rows(
|
|
2300
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2301
|
-
rows: &[JsonPointerStorageRow],
|
|
2302
|
-
tombstone_rows: usize,
|
|
2303
|
-
) -> Result<TrackedStateUpdateFixture, LixError> {
|
|
2304
|
-
let context = TrackedStateContext::new();
|
|
2305
|
-
let base_rows = json_pointer_tracked_rows(rows, "json-pointer-base", false);
|
|
2306
|
-
write_tracked_root(backend, &context, "json-pointer-base", None, &base_rows).await?;
|
|
2307
|
-
let mut child_rows = json_pointer_tracked_rows(
|
|
2308
|
-
&rows[..tombstone_rows.min(rows.len())],
|
|
2309
|
-
"json-pointer-child",
|
|
2310
|
-
true,
|
|
2311
|
-
);
|
|
2312
|
-
for row in &mut child_rows {
|
|
2313
|
-
row.snapshot_content = None;
|
|
2314
|
-
}
|
|
2315
|
-
Ok(TrackedStateUpdateFixture {
|
|
2316
|
-
context,
|
|
2317
|
-
rows: child_rows,
|
|
2318
|
-
})
|
|
2319
|
-
}
|
|
2320
|
-
|
|
2321
|
-
pub async fn prepare_json_pointer_tracked_state_diff_delta_chain(
|
|
2322
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2323
|
-
rows: &[JsonPointerStorageRow],
|
|
2324
|
-
delta_commits: usize,
|
|
2325
|
-
updated_rows_per_commit: usize,
|
|
2326
|
-
) -> Result<JsonPointerTrackedStateDiffFixture, LixError> {
|
|
2327
|
-
let (context, final_commit_id) =
|
|
2328
|
-
write_json_pointer_delta_chain(backend, rows, delta_commits, updated_rows_per_commit)
|
|
2329
|
-
.await?;
|
|
2330
|
-
Ok(JsonPointerTrackedStateDiffFixture {
|
|
2331
|
-
context,
|
|
2332
|
-
left_commit_id: "json-pointer-base".to_string(),
|
|
2333
|
-
right_commit_id: final_commit_id,
|
|
2334
|
-
expected_entries: updated_rows_per_commit.min(rows.len()),
|
|
2335
|
-
})
|
|
2336
|
-
}
|
|
2337
|
-
|
|
2338
|
-
pub async fn prepare_json_pointer_tracked_state_materialize_delta_chain(
|
|
2339
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2340
|
-
rows: &[JsonPointerStorageRow],
|
|
2341
|
-
delta_commits: usize,
|
|
2342
|
-
updated_rows_per_commit: usize,
|
|
2343
|
-
) -> Result<TrackedStateMaterializeFixture, LixError> {
|
|
2344
|
-
let (context, final_commit_id) =
|
|
2345
|
-
write_json_pointer_delta_chain(backend, rows, delta_commits, updated_rows_per_commit)
|
|
2346
|
-
.await?;
|
|
2347
|
-
Ok(TrackedStateMaterializeFixture {
|
|
2348
|
-
context,
|
|
2349
|
-
commit_id: final_commit_id,
|
|
2350
|
-
expected_rows: rows.len(),
|
|
2351
|
-
})
|
|
2352
|
-
}
|
|
2353
|
-
|
|
2354
|
-
pub async fn json_pointer_tracked_state_changed_keys_prepared(
|
|
2355
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2356
|
-
fixture: &JsonPointerTrackedStateDiffFixture,
|
|
2357
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2358
|
-
let mut reader = fixture
|
|
2359
|
-
.context
|
|
2360
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2361
|
-
let diff = reader
|
|
2362
|
-
.diff_commits(
|
|
2363
|
-
&fixture.left_commit_id,
|
|
2364
|
-
&fixture.right_commit_id,
|
|
2365
|
-
&TrackedStateDiffRequest::default(),
|
|
2366
|
-
)
|
|
2367
|
-
.await?;
|
|
2368
|
-
Ok(report(
|
|
2369
|
-
fixture.expected_entries,
|
|
2370
|
-
diff.entries.len(),
|
|
2371
|
-
Duration::ZERO,
|
|
2372
|
-
))
|
|
2373
|
-
}
|
|
2374
|
-
|
|
2375
|
-
pub async fn prepare_untracked_state_write_rows(
|
|
2376
|
-
config: StorageBenchConfig,
|
|
2377
|
-
) -> Result<UntrackedStateWriteFixture, LixError> {
|
|
2378
|
-
Ok(UntrackedStateWriteFixture {
|
|
2379
|
-
context: UntrackedStateContext::new(),
|
|
2380
|
-
rows: untracked_rows(config),
|
|
2381
|
-
})
|
|
2382
|
-
}
|
|
2383
|
-
|
|
2384
|
-
pub async fn untracked_state_write_rows_prepared(
|
|
2385
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2386
|
-
fixture: &UntrackedStateWriteFixture,
|
|
2387
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2388
|
-
write_untracked_rows(backend, &fixture.context, &fixture.rows).await?;
|
|
2389
|
-
let verified_rows = scan_untracked(
|
|
2390
|
-
backend,
|
|
2391
|
-
&fixture.context,
|
|
2392
|
-
UntrackedStateScanRequest::default(),
|
|
2393
|
-
)
|
|
2394
|
-
.await?
|
|
2395
|
-
.len();
|
|
2396
|
-
Ok(report(fixture.rows.len(), verified_rows, Duration::ZERO))
|
|
2397
|
-
}
|
|
2398
|
-
|
|
2399
|
-
pub async fn prepare_untracked_state_read(
|
|
2400
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2401
|
-
config: StorageBenchConfig,
|
|
2402
|
-
) -> Result<UntrackedStateReadFixture, LixError> {
|
|
2403
|
-
let context = UntrackedStateContext::new();
|
|
2404
|
-
let rows = untracked_rows(config);
|
|
2405
|
-
write_untracked_rows(backend, &context, &rows).await?;
|
|
2406
|
-
Ok(UntrackedStateReadFixture {
|
|
2407
|
-
context,
|
|
2408
|
-
rows: config.rows,
|
|
2409
|
-
key_pattern: config.key_pattern,
|
|
2410
|
-
selectivity: config.selectivity,
|
|
2411
|
-
})
|
|
2412
|
-
}
|
|
2413
|
-
|
|
2414
|
-
pub async fn untracked_state_read_point_hit_prepared(
|
|
2415
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2416
|
-
fixture: &UntrackedStateReadFixture,
|
|
2417
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2418
|
-
let mut verified_rows = 0;
|
|
2419
|
-
let mut reader = fixture
|
|
2420
|
-
.context
|
|
2421
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2422
|
-
for index in 0..fixture.rows {
|
|
2423
|
-
if reader
|
|
2424
|
-
.load_row(&UntrackedStateRowRequest {
|
|
2425
|
-
schema_key: untracked_schema_key(index, StorageBenchSelectivity::Percent100),
|
|
2426
|
-
version_id: "bench-version".to_string(),
|
|
2427
|
-
entity_id: EntityIdentity::single(entity_id(
|
|
2428
|
-
"untracked",
|
|
2429
|
-
index,
|
|
2430
|
-
fixture.key_pattern,
|
|
2431
|
-
)),
|
|
2432
|
-
file_id: NullableKeyFilter::Value("bench.json".to_string()),
|
|
2433
|
-
})
|
|
2434
|
-
.await?
|
|
2435
|
-
.is_some()
|
|
2436
|
-
{
|
|
2437
|
-
verified_rows += 1;
|
|
2438
|
-
}
|
|
2439
|
-
}
|
|
2440
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
2441
|
-
}
|
|
2442
|
-
|
|
2443
|
-
pub async fn untracked_state_read_point_hit_constant_prepared(
|
|
2444
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2445
|
-
fixture: &UntrackedStateReadFixture,
|
|
2446
|
-
measured_reads: usize,
|
|
2447
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2448
|
-
let mut verified_rows = 0;
|
|
2449
|
-
let mut reader = fixture
|
|
2450
|
-
.context
|
|
2451
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2452
|
-
for index in 0..measured_reads.min(fixture.rows) {
|
|
2453
|
-
if reader
|
|
2454
|
-
.load_row(&UntrackedStateRowRequest {
|
|
2455
|
-
schema_key: untracked_schema_key(index, StorageBenchSelectivity::Percent100),
|
|
2456
|
-
version_id: "bench-version".to_string(),
|
|
2457
|
-
entity_id: EntityIdentity::single(entity_id(
|
|
2458
|
-
"untracked",
|
|
2459
|
-
index,
|
|
2460
|
-
fixture.key_pattern,
|
|
2461
|
-
)),
|
|
2462
|
-
file_id: NullableKeyFilter::Value("bench.json".to_string()),
|
|
2463
|
-
})
|
|
2464
|
-
.await?
|
|
2465
|
-
.is_some()
|
|
2466
|
-
{
|
|
2467
|
-
verified_rows += 1;
|
|
2468
|
-
}
|
|
2469
|
-
}
|
|
2470
|
-
Ok(report(
|
|
2471
|
-
measured_reads.min(fixture.rows),
|
|
2472
|
-
verified_rows,
|
|
2473
|
-
Duration::ZERO,
|
|
2474
|
-
))
|
|
2475
|
-
}
|
|
2476
|
-
|
|
2477
|
-
pub async fn untracked_state_read_point_miss_prepared(
|
|
2478
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2479
|
-
fixture: &UntrackedStateReadFixture,
|
|
2480
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2481
|
-
let mut misses = 0;
|
|
2482
|
-
let mut reader = fixture
|
|
2483
|
-
.context
|
|
2484
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2485
|
-
for index in 0..fixture.rows {
|
|
2486
|
-
if reader
|
|
2487
|
-
.load_row(&UntrackedStateRowRequest {
|
|
2488
|
-
schema_key: "bench_untracked_entity".to_string(),
|
|
2489
|
-
version_id: "bench-version".to_string(),
|
|
2490
|
-
entity_id: EntityIdentity::single(format!("missing-{index}")),
|
|
2491
|
-
file_id: NullableKeyFilter::Value("bench.json".to_string()),
|
|
2492
|
-
})
|
|
2493
|
-
.await?
|
|
2494
|
-
.is_none()
|
|
2495
|
-
{
|
|
2496
|
-
misses += 1;
|
|
2497
|
-
}
|
|
2498
|
-
}
|
|
2499
|
-
Ok(report(fixture.rows, misses, Duration::ZERO))
|
|
2500
|
-
}
|
|
2501
|
-
|
|
2502
|
-
pub async fn untracked_state_scan_all_prepared(
|
|
2503
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2504
|
-
fixture: &UntrackedStateReadFixture,
|
|
2505
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2506
|
-
let verified_rows = scan_untracked(
|
|
2507
|
-
backend,
|
|
2508
|
-
&fixture.context,
|
|
2509
|
-
UntrackedStateScanRequest::default(),
|
|
2510
|
-
)
|
|
2511
|
-
.await?
|
|
2512
|
-
.len();
|
|
2513
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
2514
|
-
}
|
|
2515
|
-
|
|
2516
|
-
pub async fn untracked_state_scan_keys_only_prepared(
|
|
2517
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2518
|
-
fixture: &UntrackedStateReadFixture,
|
|
2519
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2520
|
-
let verified_rows = scan_untracked(
|
|
2521
|
-
backend,
|
|
2522
|
-
&fixture.context,
|
|
2523
|
-
UntrackedStateScanRequest {
|
|
2524
|
-
projection: UntrackedStateProjection {
|
|
2525
|
-
columns: vec!["entity_id".to_string()],
|
|
2526
|
-
},
|
|
2527
|
-
..Default::default()
|
|
2528
|
-
},
|
|
2529
|
-
)
|
|
2530
|
-
.await?
|
|
2531
|
-
.len();
|
|
2532
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
2533
|
-
}
|
|
2534
|
-
|
|
2535
|
-
pub async fn untracked_state_scan_headers_only_prepared(
|
|
2536
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2537
|
-
fixture: &UntrackedStateReadFixture,
|
|
2538
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2539
|
-
let verified_rows = scan_untracked(
|
|
2540
|
-
backend,
|
|
2541
|
-
&fixture.context,
|
|
2542
|
-
UntrackedStateScanRequest {
|
|
2543
|
-
projection: UntrackedStateProjection {
|
|
2544
|
-
columns: untracked_state_header_columns(),
|
|
2545
|
-
},
|
|
2546
|
-
..Default::default()
|
|
2547
|
-
},
|
|
2548
|
-
)
|
|
2549
|
-
.await?
|
|
2550
|
-
.len();
|
|
2551
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
2552
|
-
}
|
|
2553
|
-
|
|
2554
|
-
pub async fn untracked_state_scan_full_rows_prepared(
|
|
2555
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2556
|
-
fixture: &UntrackedStateReadFixture,
|
|
2557
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2558
|
-
untracked_state_scan_all_prepared(backend, fixture).await
|
|
2559
|
-
}
|
|
2560
|
-
|
|
2561
|
-
pub async fn untracked_state_scan_version_prepared(
|
|
2562
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2563
|
-
fixture: &UntrackedStateReadFixture,
|
|
2564
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2565
|
-
let verified_rows = scan_untracked(
|
|
2566
|
-
backend,
|
|
2567
|
-
&fixture.context,
|
|
2568
|
-
UntrackedStateScanRequest {
|
|
2569
|
-
filter: UntrackedStateFilter {
|
|
2570
|
-
version_ids: vec!["bench-version".to_string()],
|
|
2571
|
-
..Default::default()
|
|
2572
|
-
},
|
|
2573
|
-
..Default::default()
|
|
2574
|
-
},
|
|
2575
|
-
)
|
|
2576
|
-
.await?
|
|
2577
|
-
.len();
|
|
2578
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
2579
|
-
}
|
|
2580
|
-
|
|
2581
|
-
pub async fn untracked_state_scan_schema_prepared(
|
|
2582
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2583
|
-
fixture: &UntrackedStateReadFixture,
|
|
2584
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2585
|
-
let verified_rows = scan_untracked(
|
|
2586
|
-
backend,
|
|
2587
|
-
&fixture.context,
|
|
2588
|
-
UntrackedStateScanRequest {
|
|
2589
|
-
filter: UntrackedStateFilter {
|
|
2590
|
-
schema_keys: vec![untracked_schema_key(0, StorageBenchSelectivity::Percent100)],
|
|
2591
|
-
..Default::default()
|
|
2592
|
-
},
|
|
2593
|
-
..Default::default()
|
|
2594
|
-
},
|
|
2595
|
-
)
|
|
2596
|
-
.await?
|
|
2597
|
-
.len();
|
|
2598
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
2599
|
-
}
|
|
2600
|
-
|
|
2601
|
-
pub async fn untracked_state_scan_schema_selective_prepared(
|
|
2602
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2603
|
-
fixture: &UntrackedStateReadFixture,
|
|
2604
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2605
|
-
let verified_rows = scan_untracked(
|
|
2606
|
-
backend,
|
|
2607
|
-
&fixture.context,
|
|
2608
|
-
UntrackedStateScanRequest {
|
|
2609
|
-
filter: UntrackedStateFilter {
|
|
2610
|
-
schema_keys: vec![UNTRACKED_MATCH_SCHEMA_KEY.to_string()],
|
|
2611
|
-
..Default::default()
|
|
2612
|
-
},
|
|
2613
|
-
..Default::default()
|
|
2614
|
-
},
|
|
2615
|
-
)
|
|
2616
|
-
.await?
|
|
2617
|
-
.len();
|
|
2618
|
-
Ok(report(
|
|
2619
|
-
fixture.selectivity.expected_rows(fixture.rows),
|
|
2620
|
-
verified_rows,
|
|
2621
|
-
Duration::ZERO,
|
|
2622
|
-
))
|
|
2623
|
-
}
|
|
2624
|
-
|
|
2625
|
-
pub async fn prepare_untracked_state_overwrite(
|
|
2626
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2627
|
-
config: StorageBenchConfig,
|
|
2628
|
-
) -> Result<UntrackedStateWriteFixture, LixError> {
|
|
2629
|
-
let context = UntrackedStateContext::new();
|
|
2630
|
-
let rows = untracked_rows(config);
|
|
2631
|
-
write_untracked_rows(backend, &context, &rows).await?;
|
|
2632
|
-
let mut updated_rows =
|
|
2633
|
-
untracked_rows(config.with_rows(config.update_fraction.rows(config.rows)));
|
|
2634
|
-
for (index, row) in updated_rows.iter_mut().enumerate() {
|
|
2635
|
-
row.snapshot_content = Some(updated_snapshot_content(index, config.state_payload_bytes));
|
|
2636
|
-
}
|
|
2637
|
-
Ok(UntrackedStateWriteFixture {
|
|
2638
|
-
context,
|
|
2639
|
-
rows: updated_rows,
|
|
2640
|
-
})
|
|
2641
|
-
}
|
|
2642
|
-
|
|
2643
|
-
pub async fn prepare_untracked_state_insert_new_keys(
|
|
2644
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2645
|
-
config: StorageBenchConfig,
|
|
2646
|
-
) -> Result<UntrackedStateWriteFixture, LixError> {
|
|
2647
|
-
let context = UntrackedStateContext::new();
|
|
2648
|
-
let rows = untracked_rows(config);
|
|
2649
|
-
write_untracked_rows(backend, &context, &rows).await?;
|
|
2650
|
-
let mut new_rows = untracked_rows(config);
|
|
2651
|
-
for (index, row) in new_rows.iter_mut().enumerate() {
|
|
2652
|
-
row.entity_id =
|
|
2653
|
-
EntityIdentity::single(entity_id("untracked-new", index, config.key_pattern));
|
|
2654
|
-
}
|
|
2655
|
-
Ok(UntrackedStateWriteFixture {
|
|
2656
|
-
context,
|
|
2657
|
-
rows: new_rows,
|
|
2658
|
-
})
|
|
2659
|
-
}
|
|
2660
|
-
|
|
2661
|
-
pub async fn untracked_state_overwrite_existing_prepared(
|
|
2662
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2663
|
-
fixture: &UntrackedStateWriteFixture,
|
|
2664
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2665
|
-
write_untracked_rows(backend, &fixture.context, &fixture.rows).await?;
|
|
2666
|
-
let verified_rows = scan_untracked(
|
|
2667
|
-
backend,
|
|
2668
|
-
&fixture.context,
|
|
2669
|
-
UntrackedStateScanRequest::default(),
|
|
2670
|
-
)
|
|
2671
|
-
.await?
|
|
2672
|
-
.len();
|
|
2673
|
-
Ok(report(fixture.rows.len(), verified_rows, Duration::ZERO))
|
|
2674
|
-
}
|
|
2675
|
-
|
|
2676
|
-
pub async fn prepare_changelog_append_changes(
|
|
2677
|
-
config: StorageBenchConfig,
|
|
2678
|
-
) -> Result<ChangelogAppendFixture, LixError> {
|
|
2679
|
-
Ok(ChangelogAppendFixture {
|
|
2680
|
-
context: CommitStoreContext::new(),
|
|
2681
|
-
changes: changelog_materialized_changes(config),
|
|
2682
|
-
})
|
|
2683
|
-
}
|
|
2684
|
-
|
|
2685
|
-
pub async fn prepare_changelog_append_tombstones(
|
|
2686
|
-
config: StorageBenchConfig,
|
|
2687
|
-
) -> Result<ChangelogAppendFixture, LixError> {
|
|
2688
|
-
Ok(ChangelogAppendFixture {
|
|
2689
|
-
context: CommitStoreContext::new(),
|
|
2690
|
-
changes: changelog_tombstone_changes(config),
|
|
2691
|
-
})
|
|
2692
|
-
}
|
|
2693
|
-
|
|
2694
|
-
pub async fn prepare_changelog_append_metadata(
|
|
2695
|
-
config: StorageBenchConfig,
|
|
2696
|
-
) -> Result<ChangelogAppendFixture, LixError> {
|
|
2697
|
-
Ok(ChangelogAppendFixture {
|
|
2698
|
-
context: CommitStoreContext::new(),
|
|
2699
|
-
changes: changelog_metadata_changes(config),
|
|
2700
|
-
})
|
|
2701
|
-
}
|
|
2702
|
-
|
|
2703
|
-
pub async fn prepare_changelog_append_shared_payload(
|
|
2704
|
-
config: StorageBenchConfig,
|
|
2705
|
-
) -> Result<ChangelogAppendFixture, LixError> {
|
|
2706
|
-
Ok(ChangelogAppendFixture {
|
|
2707
|
-
context: CommitStoreContext::new(),
|
|
2708
|
-
changes: changelog_shared_payload_changes(config),
|
|
2709
|
-
})
|
|
2710
|
-
}
|
|
2711
|
-
|
|
2712
|
-
pub async fn prepare_changelog_append_shared_metadata(
|
|
2713
|
-
config: StorageBenchConfig,
|
|
2714
|
-
) -> Result<ChangelogAppendFixture, LixError> {
|
|
2715
|
-
Ok(ChangelogAppendFixture {
|
|
2716
|
-
context: CommitStoreContext::new(),
|
|
2717
|
-
changes: changelog_shared_metadata_changes(config),
|
|
2718
|
-
})
|
|
2719
|
-
}
|
|
2720
|
-
|
|
2721
|
-
pub async fn prepare_changelog_append_shared_payload_and_metadata(
|
|
2722
|
-
config: StorageBenchConfig,
|
|
2723
|
-
) -> Result<ChangelogAppendFixture, LixError> {
|
|
2724
|
-
Ok(ChangelogAppendFixture {
|
|
2725
|
-
context: CommitStoreContext::new(),
|
|
2726
|
-
changes: changelog_shared_payload_and_metadata_changes(config),
|
|
2727
|
-
})
|
|
2728
|
-
}
|
|
2729
|
-
|
|
2730
|
-
pub async fn prepare_changelog_append_composite_entity_ids(
|
|
2731
|
-
config: StorageBenchConfig,
|
|
2732
|
-
) -> Result<ChangelogAppendFixture, LixError> {
|
|
2733
|
-
Ok(ChangelogAppendFixture {
|
|
2734
|
-
context: CommitStoreContext::new(),
|
|
2735
|
-
changes: changelog_composite_entity_id_changes(config),
|
|
2736
|
-
})
|
|
2737
|
-
}
|
|
2738
|
-
|
|
2739
|
-
pub async fn prepare_changelog_codec(
|
|
2740
|
-
config: StorageBenchConfig,
|
|
2741
|
-
) -> Result<ChangelogCodecFixture, LixError> {
|
|
2742
|
-
let changes = changelog_changes(config);
|
|
2743
|
-
let encoded_changes = changes
|
|
2744
|
-
.iter()
|
|
2745
|
-
.map(|change| crate::commit_store::codec::encode_change_ref(change.as_ref()))
|
|
2746
|
-
.collect::<Result<Vec<_>, _>>()?;
|
|
2747
|
-
Ok(ChangelogCodecFixture {
|
|
2748
|
-
changes,
|
|
2749
|
-
encoded_changes,
|
|
2750
|
-
})
|
|
2751
|
-
}
|
|
2752
|
-
|
|
2753
|
-
pub async fn changelog_append_changes_prepared(
|
|
2754
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2755
|
-
fixture: &ChangelogAppendFixture,
|
|
2756
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2757
|
-
append_changelog_changes(backend, &fixture.context, &fixture.changes).await?;
|
|
2758
|
-
let reader = fixture
|
|
2759
|
-
.context
|
|
2760
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2761
|
-
let verified_rows = reader
|
|
2762
|
-
.scan_changes(&ChangeScanRequest::default())
|
|
2763
|
-
.await?
|
|
2764
|
-
.len();
|
|
2765
|
-
Ok(report(fixture.changes.len(), verified_rows, Duration::ZERO))
|
|
2766
|
-
}
|
|
2767
|
-
|
|
2768
|
-
pub async fn prepare_changelog_read(
|
|
2769
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2770
|
-
config: StorageBenchConfig,
|
|
2771
|
-
) -> Result<ChangelogReadFixture, LixError> {
|
|
2772
|
-
let context = CommitStoreContext::new();
|
|
2773
|
-
let changes = changelog_materialized_changes(config);
|
|
2774
|
-
append_changelog_changes(backend, &context, &changes).await?;
|
|
2775
|
-
Ok(ChangelogReadFixture {
|
|
2776
|
-
context,
|
|
2777
|
-
rows: config.rows,
|
|
2778
|
-
})
|
|
2779
|
-
}
|
|
2780
|
-
|
|
2781
|
-
pub async fn prepare_changelog_read_with_selectivity(
|
|
2782
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2783
|
-
config: StorageBenchConfig,
|
|
2784
|
-
) -> Result<ChangelogReadFixture, LixError> {
|
|
2785
|
-
let context = CommitStoreContext::new();
|
|
2786
|
-
let changes = changelog_selective_changes(config);
|
|
2787
|
-
append_changelog_changes(backend, &context, &changes).await?;
|
|
2788
|
-
Ok(ChangelogReadFixture {
|
|
2789
|
-
context,
|
|
2790
|
-
rows: config.rows,
|
|
2791
|
-
})
|
|
2792
|
-
}
|
|
2793
|
-
|
|
2794
|
-
pub async fn prepare_changelog_read_entity_history(
|
|
2795
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2796
|
-
config: StorageBenchConfig,
|
|
2797
|
-
) -> Result<ChangelogReadFixture, LixError> {
|
|
2798
|
-
let context = CommitStoreContext::new();
|
|
2799
|
-
let changes = changelog_entity_history_changes(config);
|
|
2800
|
-
append_changelog_changes(backend, &context, &changes).await?;
|
|
2801
|
-
Ok(ChangelogReadFixture {
|
|
2802
|
-
context,
|
|
2803
|
-
rows: config.rows,
|
|
2804
|
-
})
|
|
2805
|
-
}
|
|
2806
|
-
|
|
2807
|
-
pub async fn changelog_encode_only_prepared(
|
|
2808
|
-
fixture: &ChangelogCodecFixture,
|
|
2809
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2810
|
-
let mut verified_rows = 0;
|
|
2811
|
-
let mut encoded_bytes = 0;
|
|
2812
|
-
for change in &fixture.changes {
|
|
2813
|
-
encoded_bytes += crate::commit_store::codec::encode_change_ref(change.as_ref())?.len();
|
|
2814
|
-
verified_rows += 1;
|
|
2815
|
-
}
|
|
2816
|
-
Ok(report(
|
|
2817
|
-
fixture.changes.len(),
|
|
2818
|
-
verified_rows + usize::from(encoded_bytes == 0),
|
|
2819
|
-
Duration::ZERO,
|
|
2820
|
-
))
|
|
2821
|
-
}
|
|
2822
|
-
|
|
2823
|
-
pub async fn changelog_decode_only_prepared(
|
|
2824
|
-
fixture: &ChangelogCodecFixture,
|
|
2825
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2826
|
-
let mut verified_rows = 0;
|
|
2827
|
-
let mut decoded_bytes = 0;
|
|
2828
|
-
for bytes in &fixture.encoded_changes {
|
|
2829
|
-
let change = crate::commit_store::codec::decode_change(bytes)?;
|
|
2830
|
-
decoded_bytes += change.schema_key.len();
|
|
2831
|
-
verified_rows += 1;
|
|
2832
|
-
}
|
|
2833
|
-
Ok(report(
|
|
2834
|
-
fixture.encoded_changes.len(),
|
|
2835
|
-
verified_rows + usize::from(decoded_bytes == 0),
|
|
2836
|
-
Duration::ZERO,
|
|
2837
|
-
))
|
|
2838
|
-
}
|
|
2839
|
-
|
|
2840
|
-
pub async fn changelog_load_changes_hit_prepared(
|
|
2841
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2842
|
-
fixture: &ChangelogReadFixture,
|
|
2843
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2844
|
-
let reader = fixture
|
|
2845
|
-
.context
|
|
2846
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2847
|
-
let change_ids = (0..fixture.rows)
|
|
2848
|
-
.map(|index| format!("bench-change-{index}"))
|
|
2849
|
-
.collect::<Vec<_>>();
|
|
2850
|
-
let verified_rows = reader
|
|
2851
|
-
.load_changes(&change_ids)
|
|
2852
|
-
.await?
|
|
2853
|
-
.into_iter()
|
|
2854
|
-
.filter(Option::is_some)
|
|
2855
|
-
.count();
|
|
2856
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
2857
|
-
}
|
|
2858
|
-
|
|
2859
|
-
pub async fn changelog_load_changes_miss_prepared(
|
|
2860
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2861
|
-
fixture: &ChangelogReadFixture,
|
|
2862
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2863
|
-
let reader = fixture
|
|
2864
|
-
.context
|
|
2865
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2866
|
-
let change_ids = (0..fixture.rows)
|
|
2867
|
-
.map(|index| format!("missing-change-{index}"))
|
|
2868
|
-
.collect::<Vec<_>>();
|
|
2869
|
-
let misses = reader
|
|
2870
|
-
.load_changes(&change_ids)
|
|
2871
|
-
.await?
|
|
2872
|
-
.into_iter()
|
|
2873
|
-
.filter(Option::is_none)
|
|
2874
|
-
.count();
|
|
2875
|
-
Ok(report(fixture.rows, misses, Duration::ZERO))
|
|
2876
|
-
}
|
|
2877
|
-
|
|
2878
|
-
pub async fn changelog_scan_all_prepared(
|
|
2879
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2880
|
-
fixture: &ChangelogReadFixture,
|
|
2881
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2882
|
-
let reader = fixture
|
|
2883
|
-
.context
|
|
2884
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2885
|
-
let verified_rows = reader
|
|
2886
|
-
.scan_changes(&ChangeScanRequest::default())
|
|
2887
|
-
.await?
|
|
2888
|
-
.len();
|
|
2889
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
2890
|
-
}
|
|
2891
|
-
|
|
2892
|
-
pub async fn changelog_scan_full_changes_prepared(
|
|
2893
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2894
|
-
fixture: &ChangelogReadFixture,
|
|
2895
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2896
|
-
changelog_scan_all_prepared(backend, fixture).await
|
|
2897
|
-
}
|
|
2898
|
-
|
|
2899
|
-
pub async fn changelog_scan_limit_100_prepared(
|
|
2900
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2901
|
-
fixture: &ChangelogReadFixture,
|
|
2902
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2903
|
-
let reader = fixture
|
|
2904
|
-
.context
|
|
2905
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2906
|
-
let expected = fixture.rows.min(100);
|
|
2907
|
-
let verified_rows = reader
|
|
2908
|
-
.scan_changes(&ChangeScanRequest {
|
|
2909
|
-
limit: Some(expected),
|
|
2910
|
-
})
|
|
2911
|
-
.await?
|
|
2912
|
-
.len();
|
|
2913
|
-
Ok(report(expected, verified_rows, Duration::ZERO))
|
|
2914
|
-
}
|
|
2915
|
-
|
|
2916
|
-
pub async fn changelog_scan_change_set_prepared(
|
|
2917
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2918
|
-
fixture: &ChangelogReadFixture,
|
|
2919
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2920
|
-
let reader = fixture
|
|
2921
|
-
.context
|
|
2922
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2923
|
-
let change_ids = (0..fixture.rows)
|
|
2924
|
-
.map(|index| format!("bench-change-{index}"))
|
|
2925
|
-
.collect::<Vec<_>>();
|
|
2926
|
-
let verified_rows = reader
|
|
2927
|
-
.load_changes(&change_ids)
|
|
2928
|
-
.await?
|
|
2929
|
-
.into_iter()
|
|
2930
|
-
.filter(Option::is_some)
|
|
2931
|
-
.count();
|
|
2932
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
2933
|
-
}
|
|
2934
|
-
|
|
2935
|
-
pub async fn changelog_scan_schema_prepared(
|
|
2936
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2937
|
-
fixture: &ChangelogReadFixture,
|
|
2938
|
-
selectivity: StorageBenchSelectivity,
|
|
2939
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2940
|
-
let reader = fixture
|
|
2941
|
-
.context
|
|
2942
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2943
|
-
let changes = reader.scan_changes(&ChangeScanRequest::default()).await?;
|
|
2944
|
-
let verified_rows = changes
|
|
2945
|
-
.iter()
|
|
2946
|
-
.filter(|change| change.record.schema_key == CHANGELOG_MATCH_SCHEMA_KEY)
|
|
2947
|
-
.count();
|
|
2948
|
-
Ok(report(
|
|
2949
|
-
selectivity.expected_rows(fixture.rows),
|
|
2950
|
-
verified_rows,
|
|
2951
|
-
Duration::ZERO,
|
|
2952
|
-
))
|
|
2953
|
-
}
|
|
2954
|
-
|
|
2955
|
-
pub async fn changelog_scan_entity_history_prepared(
|
|
2956
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2957
|
-
fixture: &ChangelogReadFixture,
|
|
2958
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2959
|
-
let reader = fixture
|
|
2960
|
-
.context
|
|
2961
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
2962
|
-
let changes = reader.scan_changes(&ChangeScanRequest::default()).await?;
|
|
2963
|
-
let target = EntityIdentity::single(CHANGELOG_HISTORY_ENTITY_ID);
|
|
2964
|
-
let verified_rows = changes
|
|
2965
|
-
.iter()
|
|
2966
|
-
.filter(|change| change.record.entity_id == target)
|
|
2967
|
-
.count();
|
|
2968
|
-
Ok(report(
|
|
2969
|
-
fixture.rows.div_ceil(10),
|
|
2970
|
-
verified_rows,
|
|
2971
|
-
Duration::ZERO,
|
|
2972
|
-
))
|
|
2973
|
-
}
|
|
2974
|
-
|
|
2975
|
-
pub async fn prepare_commit_graph_read(
|
|
2976
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2977
|
-
config: StorageBenchConfig,
|
|
2978
|
-
) -> Result<CommitGraphReadFixture, LixError> {
|
|
2979
|
-
let changelog = CommitStoreContext::new();
|
|
2980
|
-
let mut changes = changelog_materialized_changes(config);
|
|
2981
|
-
let head_commit_id = "bench-commit-head".to_string();
|
|
2982
|
-
changes.push(commit_graph_materialized_commit_change(
|
|
2983
|
-
&head_commit_id,
|
|
2984
|
-
config.rows,
|
|
2985
|
-
));
|
|
2986
|
-
append_changelog_changes(backend, &changelog, &changes).await?;
|
|
2987
|
-
|
|
2988
|
-
Ok(CommitGraphReadFixture {
|
|
2989
|
-
head_commit_id,
|
|
2990
|
-
rows: config.rows,
|
|
2991
|
-
})
|
|
2992
|
-
}
|
|
2993
|
-
|
|
2994
|
-
pub async fn commit_graph_change_history_from_commit_prepared(
|
|
2995
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
2996
|
-
fixture: &CommitGraphReadFixture,
|
|
2997
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
2998
|
-
let graph = crate::commit_graph::CommitGraphContext::new();
|
|
2999
|
-
let mut reader = graph.reader(StorageContext::new(Arc::clone(backend)));
|
|
3000
|
-
let verified_rows = reader
|
|
3001
|
-
.change_history_from_commit(
|
|
3002
|
-
&fixture.head_commit_id,
|
|
3003
|
-
&CommitGraphChangeHistoryRequest::default(),
|
|
3004
|
-
)
|
|
3005
|
-
.await?
|
|
3006
|
-
.len();
|
|
3007
|
-
Ok(report(fixture.rows, verified_rows, Duration::ZERO))
|
|
3008
|
-
}
|
|
3009
|
-
|
|
3010
|
-
pub async fn prepare_binary_cas_write_blobs(
|
|
3011
|
-
config: StorageBenchConfig,
|
|
3012
|
-
) -> Result<BinaryCasWriteFixture, LixError> {
|
|
3013
|
-
Ok(BinaryCasWriteFixture {
|
|
3014
|
-
context: BinaryCasContext::new(),
|
|
3015
|
-
file_ids: binary_file_ids(config.rows),
|
|
3016
|
-
payloads: binary_payloads(config.rows, config.blob_bytes),
|
|
3017
|
-
})
|
|
3018
|
-
}
|
|
3019
|
-
|
|
3020
|
-
pub async fn prepare_binary_cas_write_duplicate_payload(
|
|
3021
|
-
config: StorageBenchConfig,
|
|
3022
|
-
) -> Result<BinaryCasWriteFixture, LixError> {
|
|
3023
|
-
let payload = binary_payload(0, config.blob_bytes);
|
|
3024
|
-
Ok(BinaryCasWriteFixture {
|
|
3025
|
-
context: BinaryCasContext::new(),
|
|
3026
|
-
file_ids: binary_file_ids(config.rows),
|
|
3027
|
-
payloads: (0..config.rows).map(|_| payload.clone()).collect(),
|
|
3028
|
-
})
|
|
3029
|
-
}
|
|
3030
|
-
|
|
3031
|
-
pub async fn prepare_binary_cas_write_half_duplicate_payload(
|
|
3032
|
-
config: StorageBenchConfig,
|
|
3033
|
-
) -> Result<BinaryCasWriteFixture, LixError> {
|
|
3034
|
-
Ok(BinaryCasWriteFixture {
|
|
3035
|
-
context: BinaryCasContext::new(),
|
|
3036
|
-
file_ids: binary_file_ids(config.rows),
|
|
3037
|
-
payloads: binary_half_duplicate_payloads(config.rows, config.blob_bytes),
|
|
3038
|
-
})
|
|
3039
|
-
}
|
|
3040
|
-
|
|
3041
|
-
pub async fn binary_cas_write_blobs_prepared(
|
|
3042
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3043
|
-
fixture: &BinaryCasWriteFixture,
|
|
3044
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3045
|
-
let writes = binary_blob_writes(&fixture.file_ids, &fixture.payloads);
|
|
3046
|
-
write_binary_blob_writes(backend, &fixture.context, &writes).await?;
|
|
3047
|
-
let verified_rows = count_binary_cas_manifests(backend).await?;
|
|
3048
|
-
Ok(report(writes.len(), verified_rows, Duration::ZERO))
|
|
3049
|
-
}
|
|
3050
|
-
|
|
3051
|
-
pub async fn prepare_binary_cas_read(
|
|
3052
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3053
|
-
config: StorageBenchConfig,
|
|
3054
|
-
) -> Result<BinaryCasReadFixture, LixError> {
|
|
3055
|
-
let context = BinaryCasContext::new();
|
|
3056
|
-
let payloads = binary_payloads(config.rows, config.blob_bytes);
|
|
3057
|
-
let file_ids = binary_file_ids(config.rows);
|
|
3058
|
-
let writes = binary_blob_writes(&file_ids, &payloads);
|
|
3059
|
-
write_binary_blob_writes(backend, &context, &writes).await?;
|
|
3060
|
-
let hashes = payloads
|
|
3061
|
-
.iter()
|
|
3062
|
-
.map(|payload| BlobHash::from_content(payload))
|
|
3063
|
-
.collect::<Vec<_>>();
|
|
3064
|
-
Ok(BinaryCasReadFixture {
|
|
3065
|
-
context,
|
|
3066
|
-
rows: config.rows,
|
|
3067
|
-
hashes,
|
|
3068
|
-
})
|
|
3069
|
-
}
|
|
3070
|
-
|
|
3071
|
-
pub async fn binary_cas_read_blob_hit_prepared(
|
|
3072
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3073
|
-
fixture: &BinaryCasReadFixture,
|
|
3074
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3075
|
-
let mut reader = fixture
|
|
3076
|
-
.context
|
|
3077
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
3078
|
-
let verified_rows = reader
|
|
3079
|
-
.load_bytes_many(&fixture.hashes)
|
|
3080
|
-
.await?
|
|
3081
|
-
.into_vec()
|
|
3082
|
-
.into_iter()
|
|
3083
|
-
.filter(|row| row.is_some())
|
|
3084
|
-
.count();
|
|
3085
|
-
Ok(report(fixture.hashes.len(), verified_rows, Duration::ZERO))
|
|
3086
|
-
}
|
|
3087
|
-
|
|
3088
|
-
pub async fn binary_cas_read_blob_miss_prepared(
|
|
3089
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3090
|
-
fixture: &BinaryCasReadFixture,
|
|
3091
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3092
|
-
let mut misses = 0;
|
|
3093
|
-
let mut reader = fixture
|
|
3094
|
-
.context
|
|
3095
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
3096
|
-
for index in 0..fixture.rows {
|
|
3097
|
-
let missing_hash = BlobHash::from_hex(&format!("{index:064x}"))?;
|
|
3098
|
-
if reader
|
|
3099
|
-
.load_bytes_many(&[missing_hash])
|
|
3100
|
-
.await?
|
|
3101
|
-
.get(0)
|
|
3102
|
-
.is_none()
|
|
3103
|
-
{
|
|
3104
|
-
misses += 1;
|
|
3105
|
-
}
|
|
3106
|
-
}
|
|
3107
|
-
Ok(report(fixture.rows, misses, Duration::ZERO))
|
|
3108
|
-
}
|
|
3109
|
-
|
|
3110
|
-
pub async fn prepare_json_store_write(
|
|
3111
|
-
shape: JsonStorePayloadShape,
|
|
3112
|
-
rows: usize,
|
|
3113
|
-
) -> Result<JsonStoreWriteFixture, LixError> {
|
|
3114
|
-
Ok(JsonStoreWriteFixture {
|
|
3115
|
-
context: JsonStoreContext::new(),
|
|
3116
|
-
documents: json_documents(shape, rows),
|
|
3117
|
-
})
|
|
3118
|
-
}
|
|
3119
|
-
|
|
3120
|
-
pub async fn prepare_json_store_write_dedupe(
|
|
3121
|
-
shape: JsonStorePayloadShape,
|
|
3122
|
-
rows: usize,
|
|
3123
|
-
) -> Result<JsonStoreWriteFixture, LixError> {
|
|
3124
|
-
let document = json_document(shape, 0);
|
|
3125
|
-
Ok(JsonStoreWriteFixture {
|
|
3126
|
-
context: JsonStoreContext::new(),
|
|
3127
|
-
documents: (0..rows).map(|_| document.clone()).collect(),
|
|
3128
|
-
})
|
|
3129
|
-
}
|
|
3130
|
-
|
|
3131
|
-
pub async fn json_store_write_prepared(
|
|
3132
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3133
|
-
fixture: &JsonStoreWriteFixture,
|
|
3134
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3135
|
-
let storage = StorageContext::new(Arc::clone(backend));
|
|
3136
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
3137
|
-
{
|
|
3138
|
-
let mut writes = StorageWriteSet::new();
|
|
3139
|
-
let mut writer = fixture.context.writer();
|
|
3140
|
-
writer.stage_batch(
|
|
3141
|
-
&mut writes,
|
|
3142
|
-
JsonWritePlacementRef::OutOfBand,
|
|
3143
|
-
fixture
|
|
3144
|
-
.documents
|
|
3145
|
-
.iter()
|
|
3146
|
-
.map(|document| {
|
|
3147
|
-
std::str::from_utf8(document)
|
|
3148
|
-
.map(NormalizedJsonRef::new)
|
|
3149
|
-
.map_err(|error| {
|
|
3150
|
-
LixError::new(
|
|
3151
|
-
LixError::CODE_UNKNOWN,
|
|
3152
|
-
format!("benchmark JSON document is invalid UTF-8: {error}"),
|
|
3153
|
-
)
|
|
3154
|
-
})
|
|
3155
|
-
})
|
|
3156
|
-
.collect::<Result<Vec<_>, _>>()?,
|
|
3157
|
-
)?;
|
|
3158
|
-
writes.apply(&mut transaction.as_mut()).await?;
|
|
3159
|
-
}
|
|
3160
|
-
transaction.commit().await?;
|
|
3161
|
-
Ok(report(
|
|
3162
|
-
fixture.documents.len(),
|
|
3163
|
-
fixture.documents.len(),
|
|
3164
|
-
Duration::ZERO,
|
|
3165
|
-
))
|
|
3166
|
-
}
|
|
3167
|
-
|
|
3168
|
-
pub async fn prepare_json_store_read(
|
|
3169
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3170
|
-
shape: JsonStorePayloadShape,
|
|
3171
|
-
rows: usize,
|
|
3172
|
-
) -> Result<JsonStoreReadFixture, LixError> {
|
|
3173
|
-
prepare_json_store_projection_read(
|
|
3174
|
-
backend,
|
|
3175
|
-
shape,
|
|
3176
|
-
rows,
|
|
3177
|
-
JsonStoreProjectionShape::TopLevelTarget,
|
|
3178
|
-
)
|
|
3179
|
-
.await
|
|
3180
|
-
}
|
|
3181
|
-
|
|
3182
|
-
pub async fn prepare_json_store_projection_read(
|
|
3183
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3184
|
-
shape: JsonStorePayloadShape,
|
|
3185
|
-
rows: usize,
|
|
3186
|
-
projection: JsonStoreProjectionShape,
|
|
3187
|
-
) -> Result<JsonStoreReadFixture, LixError> {
|
|
3188
|
-
let context = JsonStoreContext::new();
|
|
3189
|
-
let documents = json_documents(shape, rows);
|
|
3190
|
-
let mut refs = Vec::with_capacity(documents.len());
|
|
3191
|
-
let storage = StorageContext::new(Arc::clone(backend));
|
|
3192
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
3193
|
-
{
|
|
3194
|
-
let mut writes = StorageWriteSet::new();
|
|
3195
|
-
let mut writer = context.writer();
|
|
3196
|
-
for document in &documents {
|
|
3197
|
-
refs.push(prepare_json_ref(document)?);
|
|
3198
|
-
}
|
|
3199
|
-
writer.stage_batch(
|
|
3200
|
-
&mut writes,
|
|
3201
|
-
JsonWritePlacementRef::OutOfBand,
|
|
3202
|
-
documents
|
|
3203
|
-
.iter()
|
|
3204
|
-
.map(|document| {
|
|
3205
|
-
std::str::from_utf8(document)
|
|
3206
|
-
.map(NormalizedJsonRef::new)
|
|
3207
|
-
.map_err(|error| {
|
|
3208
|
-
LixError::new(
|
|
3209
|
-
LixError::CODE_UNKNOWN,
|
|
3210
|
-
format!("benchmark JSON document is invalid UTF-8: {error}"),
|
|
3211
|
-
)
|
|
3212
|
-
})
|
|
3213
|
-
})
|
|
3214
|
-
.collect::<Result<Vec<_>, _>>()?,
|
|
3215
|
-
)?;
|
|
3216
|
-
writes.apply(&mut transaction.as_mut()).await?;
|
|
3217
|
-
}
|
|
3218
|
-
transaction.commit().await?;
|
|
3219
|
-
Ok(JsonStoreReadFixture {
|
|
3220
|
-
context,
|
|
3221
|
-
refs,
|
|
3222
|
-
paths: json_projection_paths(projection),
|
|
3223
|
-
})
|
|
3224
|
-
}
|
|
3225
|
-
|
|
3226
|
-
pub async fn json_store_read_bytes_prepared(
|
|
3227
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3228
|
-
fixture: &JsonStoreReadFixture,
|
|
3229
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3230
|
-
let mut verified_rows = 0;
|
|
3231
|
-
let mut reader = fixture
|
|
3232
|
-
.context
|
|
3233
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
3234
|
-
let batch = reader
|
|
3235
|
-
.load_bytes_many(JsonLoadRequestRef {
|
|
3236
|
-
refs: &fixture.refs,
|
|
3237
|
-
scope: JsonReadScopeRef::OutOfBand,
|
|
3238
|
-
})
|
|
3239
|
-
.await?;
|
|
3240
|
-
for value in batch.values() {
|
|
3241
|
-
if value.is_some() {
|
|
3242
|
-
verified_rows += 1;
|
|
3243
|
-
}
|
|
3244
|
-
}
|
|
3245
|
-
Ok(report(fixture.refs.len(), verified_rows, Duration::ZERO))
|
|
3246
|
-
}
|
|
3247
|
-
|
|
3248
|
-
pub async fn json_store_read_value_prepared(
|
|
3249
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3250
|
-
fixture: &JsonStoreReadFixture,
|
|
3251
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3252
|
-
let mut verified_rows = 0;
|
|
3253
|
-
let mut reader = fixture
|
|
3254
|
-
.context
|
|
3255
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
3256
|
-
let batch = reader
|
|
3257
|
-
.load_values_many(JsonLoadRequestRef {
|
|
3258
|
-
refs: &fixture.refs,
|
|
3259
|
-
scope: JsonReadScopeRef::OutOfBand,
|
|
3260
|
-
})
|
|
3261
|
-
.await?;
|
|
3262
|
-
for value in batch.values() {
|
|
3263
|
-
if value.is_some() {
|
|
3264
|
-
verified_rows += 1;
|
|
3265
|
-
}
|
|
3266
|
-
}
|
|
3267
|
-
Ok(report(fixture.refs.len(), verified_rows, Duration::ZERO))
|
|
3268
|
-
}
|
|
3269
|
-
|
|
3270
|
-
pub async fn json_store_read_projection_prepared(
|
|
3271
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3272
|
-
fixture: &JsonStoreReadFixture,
|
|
3273
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3274
|
-
let mut verified_rows = 0;
|
|
3275
|
-
let mut reader = fixture
|
|
3276
|
-
.context
|
|
3277
|
-
.reader(StorageContext::new(Arc::clone(backend)));
|
|
3278
|
-
let batch = reader
|
|
3279
|
-
.load_projections_many(JsonProjectionLoadRequestRef {
|
|
3280
|
-
refs: &fixture.refs,
|
|
3281
|
-
scope: JsonReadScopeRef::OutOfBand,
|
|
3282
|
-
paths: &fixture.paths,
|
|
3283
|
-
})
|
|
3284
|
-
.await?;
|
|
3285
|
-
for value in batch.values() {
|
|
3286
|
-
if value.is_some() {
|
|
3287
|
-
verified_rows += 1;
|
|
3288
|
-
}
|
|
3289
|
-
}
|
|
3290
|
-
Ok(report(fixture.refs.len(), verified_rows, Duration::ZERO))
|
|
3291
|
-
}
|
|
3292
|
-
|
|
3293
|
-
pub async fn prepare_json_store_base_update_object(
|
|
3294
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3295
|
-
rows: usize,
|
|
3296
|
-
) -> Result<JsonStoreReadFixture, LixError> {
|
|
3297
|
-
prepare_json_store_base_update(backend, JsonStorePayloadShape::LargeStructured128k, rows).await
|
|
3298
|
-
}
|
|
3299
|
-
|
|
3300
|
-
pub async fn prepare_json_store_base_update_array(
|
|
3301
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3302
|
-
rows: usize,
|
|
3303
|
-
) -> Result<JsonStoreReadFixture, LixError> {
|
|
3304
|
-
prepare_json_store_base_update(backend, JsonStorePayloadShape::LargeArray128k, rows).await
|
|
3305
|
-
}
|
|
3306
|
-
|
|
3307
|
-
async fn prepare_json_store_base_update(
|
|
3308
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3309
|
-
shape: JsonStorePayloadShape,
|
|
3310
|
-
rows: usize,
|
|
3311
|
-
) -> Result<JsonStoreReadFixture, LixError> {
|
|
3312
|
-
let context = JsonStoreContext::new();
|
|
3313
|
-
let documents = json_documents(shape, rows);
|
|
3314
|
-
let mut refs = Vec::with_capacity(documents.len());
|
|
3315
|
-
let storage = StorageContext::new(Arc::clone(backend));
|
|
3316
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
3317
|
-
{
|
|
3318
|
-
let mut writes = StorageWriteSet::new();
|
|
3319
|
-
let mut writer = context.writer();
|
|
3320
|
-
for document in &documents {
|
|
3321
|
-
refs.push(prepare_json_ref(document)?);
|
|
3322
|
-
}
|
|
3323
|
-
writer.stage_batch(
|
|
3324
|
-
&mut writes,
|
|
3325
|
-
JsonWritePlacementRef::OutOfBand,
|
|
3326
|
-
documents
|
|
3327
|
-
.iter()
|
|
3328
|
-
.map(|document| {
|
|
3329
|
-
std::str::from_utf8(document)
|
|
3330
|
-
.map(NormalizedJsonRef::new)
|
|
3331
|
-
.map_err(|error| {
|
|
3332
|
-
LixError::new(
|
|
3333
|
-
LixError::CODE_UNKNOWN,
|
|
3334
|
-
format!("benchmark JSON document is invalid UTF-8: {error}"),
|
|
3335
|
-
)
|
|
3336
|
-
})
|
|
3337
|
-
})
|
|
3338
|
-
.collect::<Result<Vec<_>, _>>()?,
|
|
3339
|
-
)?;
|
|
3340
|
-
writes.apply(&mut transaction.as_mut()).await?;
|
|
3341
|
-
}
|
|
3342
|
-
transaction.commit().await?;
|
|
3343
|
-
Ok(JsonStoreReadFixture {
|
|
3344
|
-
context,
|
|
3345
|
-
refs,
|
|
3346
|
-
paths: json_projection_paths(JsonStoreProjectionShape::TopLevelTarget),
|
|
3347
|
-
})
|
|
3348
|
-
}
|
|
3349
|
-
|
|
3350
|
-
pub async fn json_store_write_against_base_object_prepared(
|
|
3351
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3352
|
-
fixture: &JsonStoreReadFixture,
|
|
3353
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3354
|
-
json_store_write_against_base_prepared(
|
|
3355
|
-
backend,
|
|
3356
|
-
fixture,
|
|
3357
|
-
JsonStorePayloadShape::LargeStructured128k,
|
|
3358
|
-
)
|
|
3359
|
-
.await
|
|
3360
|
-
}
|
|
3361
|
-
|
|
3362
|
-
pub async fn json_store_write_against_base_array_prepared(
|
|
3363
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3364
|
-
fixture: &JsonStoreReadFixture,
|
|
3365
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3366
|
-
json_store_write_against_base_prepared(backend, fixture, JsonStorePayloadShape::LargeArray128k)
|
|
3367
|
-
.await
|
|
3368
|
-
}
|
|
3369
|
-
|
|
3370
|
-
async fn json_store_write_against_base_prepared(
|
|
3371
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3372
|
-
fixture: &JsonStoreReadFixture,
|
|
3373
|
-
shape: JsonStorePayloadShape,
|
|
3374
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3375
|
-
let storage = StorageContext::new(Arc::clone(backend));
|
|
3376
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
3377
|
-
{
|
|
3378
|
-
let mut writes = StorageWriteSet::new();
|
|
3379
|
-
let mut writer = fixture.context.writer();
|
|
3380
|
-
let mut updated_documents = Vec::with_capacity(fixture.refs.len());
|
|
3381
|
-
for (index, _json_ref) in fixture.refs.iter().enumerate() {
|
|
3382
|
-
let updated = updated_json_document(shape, index);
|
|
3383
|
-
prepare_json_ref(&updated)?;
|
|
3384
|
-
updated_documents.push(updated);
|
|
3385
|
-
}
|
|
3386
|
-
writer.stage_batch(
|
|
3387
|
-
&mut writes,
|
|
3388
|
-
JsonWritePlacementRef::OutOfBand,
|
|
3389
|
-
updated_documents
|
|
3390
|
-
.iter()
|
|
3391
|
-
.map(|document| {
|
|
3392
|
-
std::str::from_utf8(document)
|
|
3393
|
-
.map(NormalizedJsonRef::new)
|
|
3394
|
-
.map_err(|error| {
|
|
3395
|
-
LixError::new(
|
|
3396
|
-
LixError::CODE_UNKNOWN,
|
|
3397
|
-
format!("benchmark JSON document is invalid UTF-8: {error}"),
|
|
3398
|
-
)
|
|
3399
|
-
})
|
|
3400
|
-
})
|
|
3401
|
-
.collect::<Result<Vec<_>, _>>()?,
|
|
3402
|
-
)?;
|
|
3403
|
-
writes.apply(&mut transaction.as_mut()).await?;
|
|
3404
|
-
}
|
|
3405
|
-
transaction.commit().await?;
|
|
3406
|
-
Ok(report(
|
|
3407
|
-
fixture.refs.len(),
|
|
3408
|
-
fixture.refs.len(),
|
|
3409
|
-
Duration::ZERO,
|
|
3410
|
-
))
|
|
3411
|
-
}
|
|
3412
|
-
|
|
3413
|
-
pub async fn tracked_state_write_root(
|
|
3414
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3415
|
-
config: StorageBenchConfig,
|
|
3416
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3417
|
-
let rows = tracked_rows(config, "bench-tracked-commit");
|
|
3418
|
-
let context = TrackedStateContext::new();
|
|
3419
|
-
let started = Instant::now();
|
|
3420
|
-
write_tracked_root(backend, &context, "bench-tracked-commit", None, &rows).await?;
|
|
3421
|
-
let elapsed = started.elapsed();
|
|
3422
|
-
let verified_rows = scan_tracked(backend, &context, "bench-tracked-commit")
|
|
3423
|
-
.await?
|
|
3424
|
-
.len();
|
|
3425
|
-
Ok(report(rows.len(), verified_rows, elapsed))
|
|
3426
|
-
}
|
|
3427
|
-
|
|
3428
|
-
pub async fn tracked_state_read_point_hit(
|
|
3429
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3430
|
-
config: StorageBenchConfig,
|
|
3431
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3432
|
-
let context = TrackedStateContext::new();
|
|
3433
|
-
let rows = tracked_rows(config, "bench-tracked-commit");
|
|
3434
|
-
write_tracked_root(backend, &context, "bench-tracked-commit", None, &rows).await?;
|
|
3435
|
-
|
|
3436
|
-
let started = Instant::now();
|
|
3437
|
-
let mut reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3438
|
-
let requests = tracked_point_hit_requests(config.rows, config.key_pattern);
|
|
3439
|
-
let verified_rows = reader
|
|
3440
|
-
.load_rows_at_commit("bench-tracked-commit", &requests)
|
|
3441
|
-
.await?
|
|
3442
|
-
.into_iter()
|
|
3443
|
-
.filter(Option::is_some)
|
|
3444
|
-
.count();
|
|
3445
|
-
Ok(report(config.rows, verified_rows, started.elapsed()))
|
|
3446
|
-
}
|
|
3447
|
-
|
|
3448
|
-
pub async fn tracked_state_read_point_miss(
|
|
3449
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3450
|
-
config: StorageBenchConfig,
|
|
3451
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3452
|
-
let context = TrackedStateContext::new();
|
|
3453
|
-
let rows = tracked_rows(config, "bench-tracked-commit");
|
|
3454
|
-
write_tracked_root(backend, &context, "bench-tracked-commit", None, &rows).await?;
|
|
3455
|
-
|
|
3456
|
-
let started = Instant::now();
|
|
3457
|
-
let mut reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3458
|
-
let requests = tracked_point_miss_requests(config.rows, StorageBenchSelectivity::Percent100);
|
|
3459
|
-
let misses = reader
|
|
3460
|
-
.load_rows_at_commit("bench-tracked-commit", &requests)
|
|
3461
|
-
.await?
|
|
3462
|
-
.into_iter()
|
|
3463
|
-
.filter(Option::is_none)
|
|
3464
|
-
.count();
|
|
3465
|
-
Ok(report(config.rows, misses, started.elapsed()))
|
|
3466
|
-
}
|
|
3467
|
-
|
|
3468
|
-
pub async fn tracked_state_scan_all(
|
|
3469
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3470
|
-
config: StorageBenchConfig,
|
|
3471
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3472
|
-
let context = TrackedStateContext::new();
|
|
3473
|
-
let rows = tracked_rows(config, "bench-tracked-commit");
|
|
3474
|
-
write_tracked_root(backend, &context, "bench-tracked-commit", None, &rows).await?;
|
|
3475
|
-
|
|
3476
|
-
let started = Instant::now();
|
|
3477
|
-
let verified_rows = scan_tracked(backend, &context, "bench-tracked-commit")
|
|
3478
|
-
.await?
|
|
3479
|
-
.len();
|
|
3480
|
-
Ok(report(config.rows, verified_rows, started.elapsed()))
|
|
3481
|
-
}
|
|
3482
|
-
|
|
3483
|
-
pub async fn tracked_state_scan_schema(
|
|
3484
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3485
|
-
config: StorageBenchConfig,
|
|
3486
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3487
|
-
let context = TrackedStateContext::new();
|
|
3488
|
-
let rows = tracked_rows(config, "bench-tracked-commit");
|
|
3489
|
-
write_tracked_root(backend, &context, "bench-tracked-commit", None, &rows).await?;
|
|
3490
|
-
|
|
3491
|
-
let started = Instant::now();
|
|
3492
|
-
let mut reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3493
|
-
let verified_rows = reader
|
|
3494
|
-
.scan_rows_at_commit(
|
|
3495
|
-
"bench-tracked-commit",
|
|
3496
|
-
&TrackedStateScanRequest {
|
|
3497
|
-
filter: TrackedStateFilter {
|
|
3498
|
-
schema_keys: vec![tracked_schema_key(0, StorageBenchSelectivity::Percent100)],
|
|
3499
|
-
..Default::default()
|
|
3500
|
-
},
|
|
3501
|
-
..Default::default()
|
|
3502
|
-
},
|
|
3503
|
-
)
|
|
3504
|
-
.await?
|
|
3505
|
-
.len();
|
|
3506
|
-
Ok(report(config.rows, verified_rows, started.elapsed()))
|
|
3507
|
-
}
|
|
3508
|
-
|
|
3509
|
-
pub async fn tracked_state_scan_file(
|
|
3510
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3511
|
-
config: StorageBenchConfig,
|
|
3512
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3513
|
-
let context = TrackedStateContext::new();
|
|
3514
|
-
let rows = tracked_rows(config, "bench-tracked-commit");
|
|
3515
|
-
write_tracked_root(backend, &context, "bench-tracked-commit", None, &rows).await?;
|
|
3516
|
-
|
|
3517
|
-
let started = Instant::now();
|
|
3518
|
-
let mut reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3519
|
-
let verified_rows = reader
|
|
3520
|
-
.scan_rows_at_commit(
|
|
3521
|
-
"bench-tracked-commit",
|
|
3522
|
-
&TrackedStateScanRequest {
|
|
3523
|
-
filter: TrackedStateFilter {
|
|
3524
|
-
file_ids: vec![NullableKeyFilter::Value("bench.json".to_string())],
|
|
3525
|
-
..Default::default()
|
|
3526
|
-
},
|
|
3527
|
-
..Default::default()
|
|
3528
|
-
},
|
|
3529
|
-
)
|
|
3530
|
-
.await?
|
|
3531
|
-
.len();
|
|
3532
|
-
Ok(report(config.rows, verified_rows, started.elapsed()))
|
|
3533
|
-
}
|
|
3534
|
-
|
|
3535
|
-
pub async fn tracked_state_update_existing(
|
|
3536
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3537
|
-
config: StorageBenchConfig,
|
|
3538
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3539
|
-
let context = TrackedStateContext::new();
|
|
3540
|
-
let rows = tracked_rows(config, "bench-tracked-parent");
|
|
3541
|
-
write_tracked_root(backend, &context, "bench-tracked-parent", None, &rows).await?;
|
|
3542
|
-
let mut updated_rows = tracked_rows(config, "bench-tracked-child");
|
|
3543
|
-
for (index, row) in updated_rows.iter_mut().enumerate() {
|
|
3544
|
-
row.snapshot_content = Some(updated_snapshot_content(index, config.state_payload_bytes));
|
|
3545
|
-
}
|
|
3546
|
-
|
|
3547
|
-
let started = Instant::now();
|
|
3548
|
-
write_tracked_root(
|
|
3549
|
-
backend,
|
|
3550
|
-
&context,
|
|
3551
|
-
"bench-tracked-child",
|
|
3552
|
-
Some("bench-tracked-parent"),
|
|
3553
|
-
&updated_rows,
|
|
3554
|
-
)
|
|
3555
|
-
.await?;
|
|
3556
|
-
let elapsed = started.elapsed();
|
|
3557
|
-
let verified_rows = scan_tracked(backend, &context, "bench-tracked-child")
|
|
3558
|
-
.await?
|
|
3559
|
-
.len();
|
|
3560
|
-
Ok(report(updated_rows.len(), verified_rows, elapsed))
|
|
3561
|
-
}
|
|
3562
|
-
|
|
3563
|
-
pub async fn untracked_state_write_rows(
|
|
3564
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3565
|
-
config: StorageBenchConfig,
|
|
3566
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3567
|
-
let rows = untracked_rows(config);
|
|
3568
|
-
let context = UntrackedStateContext::new();
|
|
3569
|
-
let started = Instant::now();
|
|
3570
|
-
write_untracked_rows(backend, &context, &rows).await?;
|
|
3571
|
-
let elapsed = started.elapsed();
|
|
3572
|
-
let verified_rows = scan_untracked(backend, &context, UntrackedStateScanRequest::default())
|
|
3573
|
-
.await?
|
|
3574
|
-
.len();
|
|
3575
|
-
Ok(report(rows.len(), verified_rows, elapsed))
|
|
3576
|
-
}
|
|
3577
|
-
|
|
3578
|
-
pub async fn untracked_state_read_point_hit(
|
|
3579
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3580
|
-
config: StorageBenchConfig,
|
|
3581
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3582
|
-
let context = UntrackedStateContext::new();
|
|
3583
|
-
let rows = untracked_rows(config);
|
|
3584
|
-
write_untracked_rows(backend, &context, &rows).await?;
|
|
3585
|
-
|
|
3586
|
-
let started = Instant::now();
|
|
3587
|
-
let mut verified_rows = 0;
|
|
3588
|
-
let mut reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3589
|
-
for index in 0..config.rows {
|
|
3590
|
-
if reader
|
|
3591
|
-
.load_row(&UntrackedStateRowRequest {
|
|
3592
|
-
schema_key: untracked_schema_key(index, StorageBenchSelectivity::Percent100),
|
|
3593
|
-
version_id: "bench-version".to_string(),
|
|
3594
|
-
entity_id: EntityIdentity::single(entity_id(
|
|
3595
|
-
"untracked",
|
|
3596
|
-
index,
|
|
3597
|
-
config.key_pattern,
|
|
3598
|
-
)),
|
|
3599
|
-
file_id: NullableKeyFilter::Value("bench.json".to_string()),
|
|
3600
|
-
})
|
|
3601
|
-
.await?
|
|
3602
|
-
.is_some()
|
|
3603
|
-
{
|
|
3604
|
-
verified_rows += 1;
|
|
3605
|
-
}
|
|
3606
|
-
}
|
|
3607
|
-
Ok(report(config.rows, verified_rows, started.elapsed()))
|
|
3608
|
-
}
|
|
3609
|
-
|
|
3610
|
-
pub async fn untracked_state_read_point_miss(
|
|
3611
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3612
|
-
config: StorageBenchConfig,
|
|
3613
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3614
|
-
let context = UntrackedStateContext::new();
|
|
3615
|
-
let rows = untracked_rows(config);
|
|
3616
|
-
write_untracked_rows(backend, &context, &rows).await?;
|
|
3617
|
-
|
|
3618
|
-
let started = Instant::now();
|
|
3619
|
-
let mut misses = 0;
|
|
3620
|
-
let mut reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3621
|
-
for index in 0..config.rows {
|
|
3622
|
-
if reader
|
|
3623
|
-
.load_row(&UntrackedStateRowRequest {
|
|
3624
|
-
schema_key: "bench_untracked_entity".to_string(),
|
|
3625
|
-
version_id: "bench-version".to_string(),
|
|
3626
|
-
entity_id: EntityIdentity::single(format!("missing-{index}")),
|
|
3627
|
-
file_id: NullableKeyFilter::Value("bench.json".to_string()),
|
|
3628
|
-
})
|
|
3629
|
-
.await?
|
|
3630
|
-
.is_none()
|
|
3631
|
-
{
|
|
3632
|
-
misses += 1;
|
|
3633
|
-
}
|
|
3634
|
-
}
|
|
3635
|
-
Ok(report(config.rows, misses, started.elapsed()))
|
|
3636
|
-
}
|
|
3637
|
-
|
|
3638
|
-
pub async fn untracked_state_scan_all(
|
|
3639
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3640
|
-
config: StorageBenchConfig,
|
|
3641
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3642
|
-
let context = UntrackedStateContext::new();
|
|
3643
|
-
let rows = untracked_rows(config);
|
|
3644
|
-
write_untracked_rows(backend, &context, &rows).await?;
|
|
3645
|
-
|
|
3646
|
-
let started = Instant::now();
|
|
3647
|
-
let verified_rows = scan_untracked(backend, &context, UntrackedStateScanRequest::default())
|
|
3648
|
-
.await?
|
|
3649
|
-
.len();
|
|
3650
|
-
Ok(report(config.rows, verified_rows, started.elapsed()))
|
|
3651
|
-
}
|
|
3652
|
-
|
|
3653
|
-
pub async fn untracked_state_scan_version(
|
|
3654
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3655
|
-
config: StorageBenchConfig,
|
|
3656
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3657
|
-
let context = UntrackedStateContext::new();
|
|
3658
|
-
let rows = untracked_rows(config);
|
|
3659
|
-
write_untracked_rows(backend, &context, &rows).await?;
|
|
3660
|
-
|
|
3661
|
-
let started = Instant::now();
|
|
3662
|
-
let verified_rows = scan_untracked(
|
|
3663
|
-
backend,
|
|
3664
|
-
&context,
|
|
3665
|
-
UntrackedStateScanRequest {
|
|
3666
|
-
filter: UntrackedStateFilter {
|
|
3667
|
-
version_ids: vec!["bench-version".to_string()],
|
|
3668
|
-
..Default::default()
|
|
3669
|
-
},
|
|
3670
|
-
..Default::default()
|
|
3671
|
-
},
|
|
3672
|
-
)
|
|
3673
|
-
.await?
|
|
3674
|
-
.len();
|
|
3675
|
-
Ok(report(config.rows, verified_rows, started.elapsed()))
|
|
3676
|
-
}
|
|
3677
|
-
|
|
3678
|
-
pub async fn untracked_state_scan_schema(
|
|
3679
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3680
|
-
config: StorageBenchConfig,
|
|
3681
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3682
|
-
let context = UntrackedStateContext::new();
|
|
3683
|
-
let rows = untracked_rows(config);
|
|
3684
|
-
write_untracked_rows(backend, &context, &rows).await?;
|
|
3685
|
-
|
|
3686
|
-
let started = Instant::now();
|
|
3687
|
-
let verified_rows = scan_untracked(
|
|
3688
|
-
backend,
|
|
3689
|
-
&context,
|
|
3690
|
-
UntrackedStateScanRequest {
|
|
3691
|
-
filter: UntrackedStateFilter {
|
|
3692
|
-
schema_keys: vec![untracked_schema_key(0, StorageBenchSelectivity::Percent100)],
|
|
3693
|
-
..Default::default()
|
|
3694
|
-
},
|
|
3695
|
-
..Default::default()
|
|
3696
|
-
},
|
|
3697
|
-
)
|
|
3698
|
-
.await?
|
|
3699
|
-
.len();
|
|
3700
|
-
Ok(report(config.rows, verified_rows, started.elapsed()))
|
|
3701
|
-
}
|
|
3702
|
-
|
|
3703
|
-
pub async fn untracked_state_overwrite_existing(
|
|
3704
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3705
|
-
config: StorageBenchConfig,
|
|
3706
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3707
|
-
let context = UntrackedStateContext::new();
|
|
3708
|
-
let rows = untracked_rows(config);
|
|
3709
|
-
write_untracked_rows(backend, &context, &rows).await?;
|
|
3710
|
-
let mut updated_rows = untracked_rows(config);
|
|
3711
|
-
for (index, row) in updated_rows.iter_mut().enumerate() {
|
|
3712
|
-
row.snapshot_content = Some(updated_snapshot_content(index, config.state_payload_bytes));
|
|
3713
|
-
}
|
|
3714
|
-
|
|
3715
|
-
let started = Instant::now();
|
|
3716
|
-
write_untracked_rows(backend, &context, &updated_rows).await?;
|
|
3717
|
-
let elapsed = started.elapsed();
|
|
3718
|
-
let verified_rows = scan_untracked(backend, &context, UntrackedStateScanRequest::default())
|
|
3719
|
-
.await?
|
|
3720
|
-
.len();
|
|
3721
|
-
Ok(report(updated_rows.len(), verified_rows, elapsed))
|
|
3722
|
-
}
|
|
3723
|
-
|
|
3724
|
-
pub async fn changelog_append_changes(
|
|
3725
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3726
|
-
config: StorageBenchConfig,
|
|
3727
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3728
|
-
let changes = changelog_materialized_changes(config);
|
|
3729
|
-
let context = CommitStoreContext::new();
|
|
3730
|
-
let started = Instant::now();
|
|
3731
|
-
append_changelog_changes(backend, &context, &changes).await?;
|
|
3732
|
-
let elapsed = started.elapsed();
|
|
3733
|
-
let reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3734
|
-
let verified_rows = reader
|
|
3735
|
-
.scan_changes(&ChangeScanRequest::default())
|
|
3736
|
-
.await?
|
|
3737
|
-
.len();
|
|
3738
|
-
Ok(report(changes.len(), verified_rows, elapsed))
|
|
3739
|
-
}
|
|
3740
|
-
|
|
3741
|
-
pub async fn changelog_load_changes_hit(
|
|
3742
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3743
|
-
config: StorageBenchConfig,
|
|
3744
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3745
|
-
let context = CommitStoreContext::new();
|
|
3746
|
-
let changes = changelog_materialized_changes(config);
|
|
3747
|
-
append_changelog_changes(backend, &context, &changes).await?;
|
|
3748
|
-
let reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3749
|
-
|
|
3750
|
-
let started = Instant::now();
|
|
3751
|
-
let change_ids = (0..config.rows)
|
|
3752
|
-
.map(|index| format!("bench-change-{index}"))
|
|
3753
|
-
.collect::<Vec<_>>();
|
|
3754
|
-
let verified_rows = reader
|
|
3755
|
-
.load_changes(&change_ids)
|
|
3756
|
-
.await?
|
|
3757
|
-
.into_iter()
|
|
3758
|
-
.filter(Option::is_some)
|
|
3759
|
-
.count();
|
|
3760
|
-
Ok(report(config.rows, verified_rows, started.elapsed()))
|
|
3761
|
-
}
|
|
3762
|
-
|
|
3763
|
-
pub async fn changelog_load_changes_miss(
|
|
3764
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3765
|
-
config: StorageBenchConfig,
|
|
3766
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3767
|
-
let context = CommitStoreContext::new();
|
|
3768
|
-
let changes = changelog_materialized_changes(config);
|
|
3769
|
-
append_changelog_changes(backend, &context, &changes).await?;
|
|
3770
|
-
let reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3771
|
-
|
|
3772
|
-
let started = Instant::now();
|
|
3773
|
-
let change_ids = (0..config.rows)
|
|
3774
|
-
.map(|index| format!("missing-change-{index}"))
|
|
3775
|
-
.collect::<Vec<_>>();
|
|
3776
|
-
let misses = reader
|
|
3777
|
-
.load_changes(&change_ids)
|
|
3778
|
-
.await?
|
|
3779
|
-
.into_iter()
|
|
3780
|
-
.filter(Option::is_none)
|
|
3781
|
-
.count();
|
|
3782
|
-
Ok(report(config.rows, misses, started.elapsed()))
|
|
3783
|
-
}
|
|
3784
|
-
|
|
3785
|
-
pub async fn changelog_scan_all(
|
|
3786
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3787
|
-
config: StorageBenchConfig,
|
|
3788
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3789
|
-
let context = CommitStoreContext::new();
|
|
3790
|
-
let changes = changelog_materialized_changes(config);
|
|
3791
|
-
append_changelog_changes(backend, &context, &changes).await?;
|
|
3792
|
-
let reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3793
|
-
|
|
3794
|
-
let started = Instant::now();
|
|
3795
|
-
let verified_rows = reader
|
|
3796
|
-
.scan_changes(&ChangeScanRequest::default())
|
|
3797
|
-
.await?
|
|
3798
|
-
.len();
|
|
3799
|
-
Ok(report(config.rows, verified_rows, started.elapsed()))
|
|
3800
|
-
}
|
|
3801
|
-
|
|
3802
|
-
pub async fn changelog_scan_limit_100(
|
|
3803
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3804
|
-
config: StorageBenchConfig,
|
|
3805
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3806
|
-
let context = CommitStoreContext::new();
|
|
3807
|
-
let changes = changelog_materialized_changes(config);
|
|
3808
|
-
append_changelog_changes(backend, &context, &changes).await?;
|
|
3809
|
-
let reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3810
|
-
let expected = config.rows.min(100);
|
|
3811
|
-
|
|
3812
|
-
let started = Instant::now();
|
|
3813
|
-
let verified_rows = reader
|
|
3814
|
-
.scan_changes(&ChangeScanRequest {
|
|
3815
|
-
limit: Some(expected),
|
|
3816
|
-
})
|
|
3817
|
-
.await?
|
|
3818
|
-
.len();
|
|
3819
|
-
Ok(report(expected, verified_rows, started.elapsed()))
|
|
3820
|
-
}
|
|
3821
|
-
|
|
3822
|
-
pub async fn binary_cas_write_blobs(
|
|
3823
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3824
|
-
config: StorageBenchConfig,
|
|
3825
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3826
|
-
let payloads = binary_payloads(config.rows, config.blob_bytes);
|
|
3827
|
-
let file_ids = binary_file_ids(config.rows);
|
|
3828
|
-
let writes = binary_blob_writes(&file_ids, &payloads);
|
|
3829
|
-
let context = BinaryCasContext::new();
|
|
3830
|
-
|
|
3831
|
-
let started = Instant::now();
|
|
3832
|
-
write_binary_blob_writes(backend, &context, &writes).await?;
|
|
3833
|
-
let elapsed = started.elapsed();
|
|
3834
|
-
let verified_rows = count_binary_cas_manifests(backend).await?;
|
|
3835
|
-
Ok(report(writes.len(), verified_rows, elapsed))
|
|
3836
|
-
}
|
|
3837
|
-
|
|
3838
|
-
pub async fn binary_cas_read_blob_hit(
|
|
3839
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3840
|
-
config: StorageBenchConfig,
|
|
3841
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3842
|
-
let context = BinaryCasContext::new();
|
|
3843
|
-
let payloads = binary_payloads(config.rows, config.blob_bytes);
|
|
3844
|
-
let file_ids = binary_file_ids(config.rows);
|
|
3845
|
-
let writes = binary_blob_writes(&file_ids, &payloads);
|
|
3846
|
-
write_binary_blob_writes(backend, &context, &writes).await?;
|
|
3847
|
-
let hashes = payloads
|
|
3848
|
-
.iter()
|
|
3849
|
-
.map(|payload| BlobHash::from_content(payload))
|
|
3850
|
-
.collect::<Vec<_>>();
|
|
3851
|
-
|
|
3852
|
-
let started = Instant::now();
|
|
3853
|
-
let mut reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3854
|
-
let verified_rows = reader
|
|
3855
|
-
.load_bytes_many(&hashes)
|
|
3856
|
-
.await?
|
|
3857
|
-
.into_vec()
|
|
3858
|
-
.into_iter()
|
|
3859
|
-
.filter(|row| row.is_some())
|
|
3860
|
-
.count();
|
|
3861
|
-
Ok(report(hashes.len(), verified_rows, started.elapsed()))
|
|
3862
|
-
}
|
|
3863
|
-
|
|
3864
|
-
pub async fn binary_cas_read_blob_miss(
|
|
3865
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3866
|
-
config: StorageBenchConfig,
|
|
3867
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3868
|
-
let context = BinaryCasContext::new();
|
|
3869
|
-
let payloads = binary_payloads(config.rows, config.blob_bytes);
|
|
3870
|
-
let file_ids = binary_file_ids(config.rows);
|
|
3871
|
-
let writes = binary_blob_writes(&file_ids, &payloads);
|
|
3872
|
-
write_binary_blob_writes(backend, &context, &writes).await?;
|
|
3873
|
-
|
|
3874
|
-
let started = Instant::now();
|
|
3875
|
-
let mut misses = 0;
|
|
3876
|
-
let mut reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
3877
|
-
for index in 0..config.rows {
|
|
3878
|
-
let missing_hash = BlobHash::from_hex(&format!("{index:064x}"))?;
|
|
3879
|
-
if reader
|
|
3880
|
-
.load_bytes_many(&[missing_hash])
|
|
3881
|
-
.await?
|
|
3882
|
-
.get(0)
|
|
3883
|
-
.is_none()
|
|
3884
|
-
{
|
|
3885
|
-
misses += 1;
|
|
3886
|
-
}
|
|
3887
|
-
}
|
|
3888
|
-
Ok(report(config.rows, misses, started.elapsed()))
|
|
3889
|
-
}
|
|
3890
|
-
|
|
3891
|
-
pub async fn binary_cas_write_duplicate_payload(
|
|
3892
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3893
|
-
config: StorageBenchConfig,
|
|
3894
|
-
) -> Result<StorageBenchReport, LixError> {
|
|
3895
|
-
let payload = binary_payload(0, config.blob_bytes);
|
|
3896
|
-
let payloads = (0..config.rows)
|
|
3897
|
-
.map(|_| payload.clone())
|
|
3898
|
-
.collect::<Vec<_>>();
|
|
3899
|
-
let file_ids = binary_file_ids(config.rows);
|
|
3900
|
-
let writes = binary_blob_writes(&file_ids, &payloads);
|
|
3901
|
-
let context = BinaryCasContext::new();
|
|
3902
|
-
|
|
3903
|
-
let started = Instant::now();
|
|
3904
|
-
write_binary_blob_writes(backend, &context, &writes).await?;
|
|
3905
|
-
let elapsed = started.elapsed();
|
|
3906
|
-
let verified_rows = count_binary_cas_manifests(backend).await?;
|
|
3907
|
-
Ok(report(writes.len(), verified_rows, elapsed))
|
|
3908
|
-
}
|
|
3909
|
-
|
|
3910
|
-
async fn write_tracked_root(
|
|
3911
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3912
|
-
context: &TrackedStateContext,
|
|
3913
|
-
commit_id: &str,
|
|
3914
|
-
parent_commit_id: Option<&str>,
|
|
3915
|
-
rows: &[MaterializedTrackedStateRow],
|
|
3916
|
-
) -> Result<(), LixError> {
|
|
3917
|
-
let storage = StorageContext::new(Arc::clone(backend));
|
|
3918
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
3919
|
-
let mut writes = StorageWriteSet::new();
|
|
3920
|
-
let changes = rows
|
|
3921
|
-
.iter()
|
|
3922
|
-
.map(tracked_bench_change_from_materialized)
|
|
3923
|
-
.collect::<Result<Vec<_>, _>>()?;
|
|
3924
|
-
let payloads = tracked_bench_json_payloads(rows, &changes);
|
|
3925
|
-
let json_report = JsonStoreContext::new().writer().stage_batch_report(
|
|
3926
|
-
&mut writes,
|
|
3927
|
-
JsonWritePlacementRef::CommitPack {
|
|
3928
|
-
commit_id,
|
|
3929
|
-
pack_id: 0,
|
|
3930
|
-
},
|
|
3931
|
-
payloads.iter().map(|(payload, json_ref)| match json_ref {
|
|
3932
|
-
Some(json_ref) => NormalizedJsonRef::trusted_prehashed(payload.as_str(), *json_ref),
|
|
3933
|
-
None => NormalizedJsonRef::new(payload.as_str()),
|
|
3934
|
-
}),
|
|
3935
|
-
)?;
|
|
3936
|
-
|
|
3937
|
-
let parent_ids = parent_commit_id
|
|
3938
|
-
.map(|parent| vec![parent.to_string()])
|
|
3939
|
-
.unwrap_or_default();
|
|
3940
|
-
let commit_change_id = format!("{commit_id}:commit");
|
|
3941
|
-
let commit = CommitDraftRef {
|
|
3942
|
-
id: commit_id,
|
|
3943
|
-
change_id: &commit_change_id,
|
|
3944
|
-
parent_ids: &parent_ids,
|
|
3945
|
-
author_account_ids: &[],
|
|
3946
|
-
created_at: rows
|
|
3947
|
-
.first()
|
|
3948
|
-
.map(|row| row.updated_at.as_str())
|
|
3949
|
-
.unwrap_or("1970-01-01T00:00:00.000Z"),
|
|
3950
|
-
};
|
|
3951
|
-
let commit_store = CommitStoreContext::new();
|
|
3952
|
-
let authored_changes = changes.iter().map(Change::as_ref).collect::<Vec<_>>();
|
|
3953
|
-
let staged = commit_store
|
|
3954
|
-
.writer(&mut transaction.as_mut(), &mut writes)
|
|
3955
|
-
.stage_tracked_commit_draft(commit, authored_changes.clone(), Vec::new())
|
|
3956
|
-
.await?;
|
|
3957
|
-
let mut deltas = Vec::with_capacity(changes.len());
|
|
3958
|
-
deltas.extend(
|
|
3959
|
-
authored_changes
|
|
3960
|
-
.iter()
|
|
3961
|
-
.zip(&staged.authored_locators)
|
|
3962
|
-
.zip(rows)
|
|
3963
|
-
.map(|((change, locator), row)| TrackedStateDeltaRef {
|
|
3964
|
-
change: *change,
|
|
3965
|
-
locator: locator.as_ref(),
|
|
3966
|
-
created_at: row.created_at.as_str(),
|
|
3967
|
-
updated_at: row.updated_at.as_str(),
|
|
3968
|
-
}),
|
|
3969
|
-
);
|
|
3970
|
-
context
|
|
3971
|
-
.writer(&mut transaction.as_mut(), &mut writes)
|
|
3972
|
-
.stage_delta_with_json_pack_indexes(
|
|
3973
|
-
commit_id,
|
|
3974
|
-
parent_commit_id,
|
|
3975
|
-
&deltas,
|
|
3976
|
-
crate::tracked_state::DeltaJsonPackIndexesRef {
|
|
3977
|
-
commit_id,
|
|
3978
|
-
pack_id: 0,
|
|
3979
|
-
indexes: &json_report.pack_indexes,
|
|
3980
|
-
},
|
|
3981
|
-
)
|
|
3982
|
-
.await?;
|
|
3983
|
-
writes.apply(&mut transaction.as_mut()).await?;
|
|
3984
|
-
transaction.commit().await
|
|
3985
|
-
}
|
|
3986
|
-
|
|
3987
|
-
async fn materialize_tracked_root(
|
|
3988
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
3989
|
-
context: &TrackedStateContext,
|
|
3990
|
-
commit_id: &str,
|
|
3991
|
-
) -> Result<(), LixError> {
|
|
3992
|
-
let storage = StorageContext::new(Arc::clone(backend));
|
|
3993
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
3994
|
-
let mut writes = StorageWriteSet::new();
|
|
3995
|
-
let commit_store = CommitStoreContext::new();
|
|
3996
|
-
context
|
|
3997
|
-
.materializer(&mut transaction.as_mut(), &mut writes, &commit_store)
|
|
3998
|
-
.materialize_root_at(commit_id)
|
|
3999
|
-
.await?;
|
|
4000
|
-
writes.apply(&mut transaction.as_mut()).await?;
|
|
4001
|
-
transaction.commit().await
|
|
4002
|
-
}
|
|
4003
|
-
|
|
4004
|
-
async fn write_tracked_delta_chain(
|
|
4005
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
4006
|
-
config: StorageBenchConfig,
|
|
4007
|
-
delta_commits: usize,
|
|
4008
|
-
updated_rows_per_commit: usize,
|
|
4009
|
-
) -> Result<(TrackedStateContext, String), LixError> {
|
|
4010
|
-
let context = TrackedStateContext::new();
|
|
4011
|
-
let base_commit_id = "bench-tracked-base";
|
|
4012
|
-
let rows = tracked_rows(config, base_commit_id);
|
|
4013
|
-
write_tracked_root(backend, &context, base_commit_id, None, &rows).await?;
|
|
4014
|
-
|
|
4015
|
-
let mut parent_commit_id = base_commit_id.to_string();
|
|
4016
|
-
for delta_index in 0..delta_commits {
|
|
4017
|
-
let commit_id = format!("bench-tracked-delta-{delta_index}");
|
|
4018
|
-
let mut updated_rows = tracked_rows(
|
|
4019
|
-
config.with_rows(updated_rows_per_commit.min(config.rows)),
|
|
4020
|
-
&commit_id,
|
|
4021
|
-
);
|
|
4022
|
-
for (row_index, row) in updated_rows.iter_mut().enumerate() {
|
|
4023
|
-
row.snapshot_content = Some(delta_chain_snapshot_content(
|
|
4024
|
-
delta_index,
|
|
4025
|
-
row_index,
|
|
4026
|
-
config.state_payload_bytes,
|
|
4027
|
-
));
|
|
4028
|
-
row.updated_at = timestamp(config.rows + delta_index * config.rows + row_index);
|
|
4029
|
-
}
|
|
4030
|
-
write_tracked_root(
|
|
4031
|
-
backend,
|
|
4032
|
-
&context,
|
|
4033
|
-
&commit_id,
|
|
4034
|
-
Some(parent_commit_id.as_str()),
|
|
4035
|
-
&updated_rows,
|
|
4036
|
-
)
|
|
4037
|
-
.await?;
|
|
4038
|
-
parent_commit_id = commit_id;
|
|
4039
|
-
}
|
|
4040
|
-
|
|
4041
|
-
Ok((context, parent_commit_id))
|
|
4042
|
-
}
|
|
4043
|
-
|
|
4044
|
-
fn tracked_bench_change_from_materialized(
|
|
4045
|
-
row: &MaterializedTrackedStateRow,
|
|
4046
|
-
) -> Result<Change, LixError> {
|
|
4047
|
-
Ok(Change {
|
|
4048
|
-
id: row.change_id.clone(),
|
|
4049
|
-
entity_id: row.entity_id.clone(),
|
|
4050
|
-
schema_key: row.schema_key.clone(),
|
|
4051
|
-
file_id: row.file_id.clone(),
|
|
4052
|
-
snapshot_ref: row
|
|
4053
|
-
.snapshot_content
|
|
4054
|
-
.as_deref()
|
|
4055
|
-
.map(|value| prepare_json_ref(value.as_bytes()))
|
|
4056
|
-
.transpose()?,
|
|
4057
|
-
metadata_ref: row
|
|
4058
|
-
.metadata
|
|
4059
|
-
.as_ref()
|
|
4060
|
-
.map(|value| {
|
|
4061
|
-
let serialized = crate::serialize_row_metadata(value);
|
|
4062
|
-
prepare_json_ref(serialized.as_bytes())
|
|
4063
|
-
})
|
|
4064
|
-
.transpose()?,
|
|
4065
|
-
created_at: row.created_at.clone(),
|
|
4066
|
-
})
|
|
4067
|
-
}
|
|
4068
|
-
|
|
4069
|
-
fn tracked_bench_json_payloads(
|
|
4070
|
-
rows: &[MaterializedTrackedStateRow],
|
|
4071
|
-
changes: &[Change],
|
|
4072
|
-
) -> Vec<(String, Option<JsonRef>)> {
|
|
4073
|
-
let mut payloads = Vec::new();
|
|
4074
|
-
for (row, change) in rows.iter().zip(changes) {
|
|
4075
|
-
if let Some(snapshot) = row.snapshot_content.as_deref() {
|
|
4076
|
-
payloads.push((snapshot.to_string(), change.snapshot_ref));
|
|
4077
|
-
}
|
|
4078
|
-
if let Some(metadata) = row.metadata.as_ref() {
|
|
4079
|
-
payloads.push((crate::serialize_row_metadata(metadata), change.metadata_ref));
|
|
4080
|
-
}
|
|
4081
|
-
}
|
|
4082
|
-
payloads
|
|
4083
|
-
}
|
|
4084
|
-
|
|
4085
|
-
async fn scan_tracked(
|
|
4086
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
4087
|
-
context: &TrackedStateContext,
|
|
4088
|
-
commit_id: &str,
|
|
4089
|
-
) -> Result<Vec<MaterializedTrackedStateRow>, LixError> {
|
|
4090
|
-
let mut reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
4091
|
-
reader
|
|
4092
|
-
.scan_rows_at_commit(commit_id, &TrackedStateScanRequest::default())
|
|
4093
|
-
.await
|
|
4094
|
-
}
|
|
4095
|
-
|
|
4096
|
-
async fn write_untracked_rows(
|
|
4097
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
4098
|
-
context: &UntrackedStateContext,
|
|
4099
|
-
rows: &[MaterializedUntrackedStateRow],
|
|
4100
|
-
) -> Result<(), LixError> {
|
|
4101
|
-
let storage = StorageContext::new(Arc::clone(backend));
|
|
4102
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
4103
|
-
{
|
|
4104
|
-
let mut writes = StorageWriteSet::new();
|
|
4105
|
-
let canonical_rows = rows
|
|
4106
|
-
.iter()
|
|
4107
|
-
.map(|row| crate::test_support::untracked_state_row_from_materialized(&mut writes, row))
|
|
4108
|
-
.collect::<Result<Vec<_>, _>>()?;
|
|
4109
|
-
let mut writer = context.writer(&mut writes);
|
|
4110
|
-
writer.stage_rows(canonical_rows.iter().map(|row| row.as_ref()))?;
|
|
4111
|
-
writes.apply(&mut transaction.as_mut()).await?;
|
|
4112
|
-
}
|
|
4113
|
-
transaction.commit().await
|
|
4114
|
-
}
|
|
4115
|
-
|
|
4116
|
-
async fn scan_untracked(
|
|
4117
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
4118
|
-
context: &UntrackedStateContext,
|
|
4119
|
-
request: UntrackedStateScanRequest,
|
|
4120
|
-
) -> Result<Vec<MaterializedUntrackedStateRow>, LixError> {
|
|
4121
|
-
let mut reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
4122
|
-
reader.scan_rows(&request).await
|
|
4123
|
-
}
|
|
4124
|
-
|
|
4125
|
-
async fn append_changelog_changes(
|
|
4126
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
4127
|
-
context: &CommitStoreContext,
|
|
4128
|
-
changes: &[MaterializedChange],
|
|
4129
|
-
) -> Result<(), LixError> {
|
|
4130
|
-
let storage = StorageContext::new(Arc::clone(backend));
|
|
4131
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
4132
|
-
{
|
|
4133
|
-
let mut writes = StorageWriteSet::new();
|
|
4134
|
-
let canonical_changes = changes
|
|
4135
|
-
.iter()
|
|
4136
|
-
.map(canonical_changelog_bench_change)
|
|
4137
|
-
.collect::<Result<Vec<_>, _>>()?;
|
|
4138
|
-
let payloads = changelog_bench_json_payloads(changes);
|
|
4139
|
-
JsonStoreContext::new().writer().stage_batch(
|
|
4140
|
-
&mut writes,
|
|
4141
|
-
JsonWritePlacementRef::OutOfBand,
|
|
4142
|
-
payloads
|
|
4143
|
-
.iter()
|
|
4144
|
-
.map(|payload| NormalizedJsonRef::new(payload.as_str())),
|
|
4145
|
-
)?;
|
|
4146
|
-
let parent_ids = Vec::new();
|
|
4147
|
-
let author_account_ids = vec!["bench-author".to_string()];
|
|
4148
|
-
{
|
|
4149
|
-
let mut transaction_ref = transaction.as_mut();
|
|
4150
|
-
let mut writer = context.writer(&mut transaction_ref, &mut writes);
|
|
4151
|
-
writer
|
|
4152
|
-
.stage_commit_draft(
|
|
4153
|
-
CommitDraftRef {
|
|
4154
|
-
id: "bench-changelog-commit-0",
|
|
4155
|
-
change_id: "bench-changelog-header-change-0",
|
|
4156
|
-
parent_ids: &parent_ids,
|
|
4157
|
-
author_account_ids: &author_account_ids,
|
|
4158
|
-
created_at: "2024-01-01T00:00:00.000Z",
|
|
4159
|
-
},
|
|
4160
|
-
canonical_changes
|
|
4161
|
-
.iter()
|
|
4162
|
-
.map(|change| change.as_ref())
|
|
4163
|
-
.collect(),
|
|
4164
|
-
Vec::new(),
|
|
4165
|
-
)
|
|
4166
|
-
.await?;
|
|
4167
|
-
}
|
|
4168
|
-
writes.apply(&mut transaction.as_mut()).await?;
|
|
4169
|
-
}
|
|
4170
|
-
transaction.commit().await
|
|
4171
|
-
}
|
|
4172
|
-
|
|
4173
|
-
async fn write_binary_blob_writes(
|
|
4174
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
4175
|
-
context: &BinaryCasContext,
|
|
4176
|
-
writes: &[BlobWrite<'_>],
|
|
4177
|
-
) -> Result<(), LixError> {
|
|
4178
|
-
let storage = StorageContext::new(Arc::clone(backend));
|
|
4179
|
-
let mut transaction = storage.begin_write_transaction().await?;
|
|
4180
|
-
{
|
|
4181
|
-
let mut writeset = StorageWriteSet::new();
|
|
4182
|
-
let mut writer = context.writer(&mut writeset);
|
|
4183
|
-
writer.stage_many(writes)?;
|
|
4184
|
-
writeset.apply(&mut transaction.as_mut()).await?;
|
|
4185
|
-
}
|
|
4186
|
-
transaction.commit().await
|
|
4187
|
-
}
|
|
4188
|
-
|
|
4189
|
-
async fn count_binary_cas_manifests(
|
|
4190
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
4191
|
-
) -> Result<usize, LixError> {
|
|
4192
|
-
let context = BinaryCasContext::new();
|
|
4193
|
-
let mut reader = context.reader(StorageContext::new(Arc::clone(backend)));
|
|
4194
|
-
reader.count_blob_manifests().await
|
|
4195
|
-
}
|
|
4196
|
-
|
|
4197
|
-
fn report(measured_rows: usize, verified_rows: usize, elapsed: Duration) -> StorageBenchReport {
|
|
4198
|
-
StorageBenchReport {
|
|
4199
|
-
measured_rows,
|
|
4200
|
-
verified_rows,
|
|
4201
|
-
elapsed,
|
|
4202
|
-
}
|
|
4203
|
-
}
|
|
4204
|
-
|
|
4205
|
-
const TRACKED_MATCH_SCHEMA_KEY: &str = "bench_tracked_entity";
|
|
4206
|
-
const TRACKED_OTHER_SCHEMA_KEY: &str = "bench_tracked_other_entity";
|
|
4207
|
-
const UNTRACKED_MATCH_SCHEMA_KEY: &str = "bench_untracked_entity";
|
|
4208
|
-
const UNTRACKED_OTHER_SCHEMA_KEY: &str = "bench_untracked_other_entity";
|
|
4209
|
-
const CHANGELOG_MATCH_SCHEMA_KEY: &str = "bench_changelog_entity";
|
|
4210
|
-
const CHANGELOG_OTHER_SCHEMA_KEY: &str = "bench_changelog_other_entity";
|
|
4211
|
-
const CHANGELOG_HISTORY_ENTITY_ID: &str = "change-entity-history-target";
|
|
4212
|
-
|
|
4213
|
-
fn tracked_rows(config: StorageBenchConfig, commit_id: &str) -> Vec<MaterializedTrackedStateRow> {
|
|
4214
|
-
(0..config.rows)
|
|
4215
|
-
.map(|index| MaterializedTrackedStateRow {
|
|
4216
|
-
entity_id: EntityIdentity::single(entity_id("tracked", index, config.key_pattern)),
|
|
4217
|
-
schema_key: tracked_schema_key(index, config.selectivity),
|
|
4218
|
-
file_id: Some("bench.json".to_string()),
|
|
4219
|
-
snapshot_content: Some(snapshot_content(index, config.state_payload_bytes)),
|
|
4220
|
-
metadata: None,
|
|
4221
|
-
deleted: false,
|
|
4222
|
-
created_at: timestamp(index),
|
|
4223
|
-
updated_at: timestamp(index),
|
|
4224
|
-
change_id: tracked_change_id(commit_id, index),
|
|
4225
|
-
commit_id: commit_id.to_string(),
|
|
4226
|
-
})
|
|
4227
|
-
.collect()
|
|
4228
|
-
}
|
|
4229
|
-
|
|
4230
|
-
fn json_pointer_tracked_rows(
|
|
4231
|
-
rows: &[JsonPointerStorageRow],
|
|
4232
|
-
commit_id: &str,
|
|
4233
|
-
updated: bool,
|
|
4234
|
-
) -> Vec<MaterializedTrackedStateRow> {
|
|
4235
|
-
rows.iter()
|
|
4236
|
-
.enumerate()
|
|
4237
|
-
.map(|(index, row)| {
|
|
4238
|
-
let value_json = if updated {
|
|
4239
|
-
row.updated_value_json.as_str()
|
|
4240
|
-
} else {
|
|
4241
|
-
row.value_json.as_str()
|
|
4242
|
-
};
|
|
4243
|
-
let value = serde_json::from_str::<serde_json::Value>(value_json)
|
|
4244
|
-
.unwrap_or_else(|_| serde_json::Value::String(value_json.to_string()));
|
|
4245
|
-
let snapshot = serde_json::json!({
|
|
4246
|
-
"path": row.path,
|
|
4247
|
-
"value": value,
|
|
4248
|
-
})
|
|
4249
|
-
.to_string();
|
|
4250
|
-
MaterializedTrackedStateRow {
|
|
4251
|
-
entity_id: EntityIdentity::single(row.path.as_str()),
|
|
4252
|
-
schema_key: "json_pointer".to_string(),
|
|
4253
|
-
file_id: None,
|
|
4254
|
-
snapshot_content: Some(snapshot),
|
|
4255
|
-
metadata: None,
|
|
4256
|
-
deleted: false,
|
|
4257
|
-
created_at: timestamp(index),
|
|
4258
|
-
updated_at: timestamp(index),
|
|
4259
|
-
change_id: tracked_change_id(commit_id, index),
|
|
4260
|
-
commit_id: commit_id.to_string(),
|
|
4261
|
-
}
|
|
4262
|
-
})
|
|
4263
|
-
.collect()
|
|
4264
|
-
}
|
|
4265
|
-
|
|
4266
|
-
async fn write_json_pointer_delta_chain(
|
|
4267
|
-
backend: &Arc<dyn Backend + Send + Sync>,
|
|
4268
|
-
rows: &[JsonPointerStorageRow],
|
|
4269
|
-
delta_commits: usize,
|
|
4270
|
-
updated_rows_per_commit: usize,
|
|
4271
|
-
) -> Result<(TrackedStateContext, String), LixError> {
|
|
4272
|
-
let context = TrackedStateContext::new();
|
|
4273
|
-
let base_commit_id = "json-pointer-base";
|
|
4274
|
-
let base_rows = json_pointer_tracked_rows(rows, base_commit_id, false);
|
|
4275
|
-
write_tracked_root(backend, &context, base_commit_id, None, &base_rows).await?;
|
|
4276
|
-
|
|
4277
|
-
let mut parent_commit_id = base_commit_id.to_string();
|
|
4278
|
-
for delta_index in 0..delta_commits {
|
|
4279
|
-
let commit_id = format!("json-pointer-delta-{delta_index}");
|
|
4280
|
-
let mut child_rows = json_pointer_tracked_rows(
|
|
4281
|
-
&rows[..updated_rows_per_commit.min(rows.len())],
|
|
4282
|
-
&commit_id,
|
|
4283
|
-
true,
|
|
4284
|
-
);
|
|
4285
|
-
for row in &mut child_rows {
|
|
4286
|
-
row.updated_at = timestamp(rows.len() + delta_index);
|
|
4287
|
-
}
|
|
4288
|
-
write_tracked_root(
|
|
4289
|
-
backend,
|
|
4290
|
-
&context,
|
|
4291
|
-
&commit_id,
|
|
4292
|
-
Some(parent_commit_id.as_str()),
|
|
4293
|
-
&child_rows,
|
|
4294
|
-
)
|
|
4295
|
-
.await?;
|
|
4296
|
-
parent_commit_id = commit_id;
|
|
4297
|
-
}
|
|
4298
|
-
|
|
4299
|
-
Ok((context, parent_commit_id))
|
|
4300
|
-
}
|
|
4301
|
-
|
|
4302
|
-
fn tracked_rows_file_selective(
|
|
4303
|
-
config: StorageBenchConfig,
|
|
4304
|
-
commit_id: &str,
|
|
4305
|
-
) -> Vec<MaterializedTrackedStateRow> {
|
|
4306
|
-
(0..config.rows)
|
|
4307
|
-
.map(|index| MaterializedTrackedStateRow {
|
|
4308
|
-
entity_id: EntityIdentity::single(entity_id("tracked", index, config.key_pattern)),
|
|
4309
|
-
schema_key: TRACKED_MATCH_SCHEMA_KEY.to_string(),
|
|
4310
|
-
file_id: Some(
|
|
4311
|
-
if config.selectivity.matches(index) {
|
|
4312
|
-
"bench-match.json"
|
|
4313
|
-
} else {
|
|
4314
|
-
"bench-other.json"
|
|
4315
|
-
}
|
|
4316
|
-
.to_string(),
|
|
4317
|
-
),
|
|
4318
|
-
snapshot_content: Some(snapshot_content(index, config.state_payload_bytes)),
|
|
4319
|
-
metadata: None,
|
|
4320
|
-
deleted: false,
|
|
4321
|
-
created_at: timestamp(index),
|
|
4322
|
-
updated_at: timestamp(index),
|
|
4323
|
-
change_id: tracked_change_id(commit_id, index),
|
|
4324
|
-
commit_id: commit_id.to_string(),
|
|
4325
|
-
})
|
|
4326
|
-
.collect()
|
|
4327
|
-
}
|
|
4328
|
-
|
|
4329
|
-
fn tracked_change_id(commit_id: &str, index: usize) -> String {
|
|
4330
|
-
format!("{commit_id}:tracked-change-{index}")
|
|
4331
|
-
}
|
|
4332
|
-
|
|
4333
|
-
fn untracked_rows(config: StorageBenchConfig) -> Vec<MaterializedUntrackedStateRow> {
|
|
4334
|
-
(0..config.rows)
|
|
4335
|
-
.map(|index| MaterializedUntrackedStateRow {
|
|
4336
|
-
entity_id: EntityIdentity::single(entity_id("untracked", index, config.key_pattern)),
|
|
4337
|
-
schema_key: untracked_schema_key(index, config.selectivity),
|
|
4338
|
-
file_id: Some("bench.json".to_string()),
|
|
4339
|
-
snapshot_content: Some(snapshot_content(index, config.state_payload_bytes)),
|
|
4340
|
-
metadata: None,
|
|
4341
|
-
deleted: false,
|
|
4342
|
-
created_at: timestamp(index),
|
|
4343
|
-
updated_at: timestamp(index),
|
|
4344
|
-
global: false,
|
|
4345
|
-
version_id: "bench-version".to_string(),
|
|
4346
|
-
})
|
|
4347
|
-
.collect()
|
|
4348
|
-
}
|
|
4349
|
-
|
|
4350
|
-
fn changelog_changes(config: StorageBenchConfig) -> Vec<Change> {
|
|
4351
|
-
changelog_materialized_changes(config)
|
|
4352
|
-
.into_iter()
|
|
4353
|
-
.map(changelog_bench_change_ref_only)
|
|
4354
|
-
.collect()
|
|
4355
|
-
}
|
|
4356
|
-
|
|
4357
|
-
fn changelog_materialized_changes(config: StorageBenchConfig) -> Vec<MaterializedChange> {
|
|
4358
|
-
(0..config.rows)
|
|
4359
|
-
.map(|index| MaterializedChange {
|
|
4360
|
-
id: format!("bench-change-{index}"),
|
|
4361
|
-
entity_id: EntityIdentity::single(entity_id(
|
|
4362
|
-
"change-entity",
|
|
4363
|
-
index,
|
|
4364
|
-
config.key_pattern,
|
|
4365
|
-
)),
|
|
4366
|
-
schema_key: "bench_changelog_entity".to_string(),
|
|
4367
|
-
file_id: Some("bench.json".to_string()),
|
|
4368
|
-
snapshot_content: Some(snapshot_content(index, config.state_payload_bytes)),
|
|
4369
|
-
metadata: None,
|
|
4370
|
-
created_at: timestamp(index),
|
|
4371
|
-
})
|
|
4372
|
-
.collect()
|
|
4373
|
-
}
|
|
4374
|
-
|
|
4375
|
-
fn commit_graph_materialized_commit_change(commit_id: &str, rows: usize) -> MaterializedChange {
|
|
4376
|
-
let snapshot_content = serde_json::json!({
|
|
4377
|
-
"id": commit_id,
|
|
4378
|
-
})
|
|
4379
|
-
.to_string();
|
|
4380
|
-
|
|
4381
|
-
MaterializedChange {
|
|
4382
|
-
id: format!("bench-commit-change-{commit_id}"),
|
|
4383
|
-
entity_id: EntityIdentity::single(commit_id.to_string()),
|
|
4384
|
-
schema_key: "lix_commit".to_string(),
|
|
4385
|
-
file_id: None,
|
|
4386
|
-
snapshot_content: Some(snapshot_content),
|
|
4387
|
-
metadata: None,
|
|
4388
|
-
created_at: timestamp(rows),
|
|
4389
|
-
}
|
|
4390
|
-
}
|
|
4391
|
-
|
|
4392
|
-
fn canonical_changelog_bench_change(change: &MaterializedChange) -> Result<Change, LixError> {
|
|
4393
|
-
let snapshot_ref = change
|
|
4394
|
-
.snapshot_content
|
|
4395
|
-
.as_ref()
|
|
4396
|
-
.map(|value| prepare_json_ref(value.as_bytes()))
|
|
4397
|
-
.transpose()?;
|
|
4398
|
-
let metadata_ref = change
|
|
4399
|
-
.metadata
|
|
4400
|
-
.as_ref()
|
|
4401
|
-
.map(|value| prepare_json_ref(value.as_bytes()))
|
|
4402
|
-
.transpose()?;
|
|
4403
|
-
Ok(Change {
|
|
4404
|
-
id: change.id.clone(),
|
|
4405
|
-
entity_id: change.entity_id.clone(),
|
|
4406
|
-
schema_key: change.schema_key.clone(),
|
|
4407
|
-
file_id: change.file_id.clone(),
|
|
4408
|
-
snapshot_ref,
|
|
4409
|
-
metadata_ref,
|
|
4410
|
-
created_at: change.created_at.clone(),
|
|
4411
|
-
})
|
|
4412
|
-
}
|
|
4413
|
-
|
|
4414
|
-
fn changelog_bench_json_payloads(changes: &[MaterializedChange]) -> Vec<String> {
|
|
4415
|
-
changes
|
|
4416
|
-
.iter()
|
|
4417
|
-
.flat_map(|change| {
|
|
4418
|
-
change
|
|
4419
|
-
.snapshot_content
|
|
4420
|
-
.iter()
|
|
4421
|
-
.chain(change.metadata.iter())
|
|
4422
|
-
.cloned()
|
|
4423
|
-
.collect::<Vec<_>>()
|
|
4424
|
-
})
|
|
4425
|
-
.collect()
|
|
4426
|
-
}
|
|
4427
|
-
|
|
4428
|
-
fn changelog_bench_change_ref_only(change: MaterializedChange) -> Change {
|
|
4429
|
-
let snapshot_ref = change
|
|
4430
|
-
.snapshot_content
|
|
4431
|
-
.as_ref()
|
|
4432
|
-
.map(|value| JsonRef::from_hash(blake3::hash(value.as_bytes())));
|
|
4433
|
-
let metadata_ref = change
|
|
4434
|
-
.metadata
|
|
4435
|
-
.as_ref()
|
|
4436
|
-
.map(|value| JsonRef::from_hash(blake3::hash(value.as_bytes())));
|
|
4437
|
-
Change {
|
|
4438
|
-
id: change.id,
|
|
4439
|
-
entity_id: change.entity_id,
|
|
4440
|
-
schema_key: change.schema_key,
|
|
4441
|
-
file_id: change.file_id,
|
|
4442
|
-
snapshot_ref,
|
|
4443
|
-
metadata_ref,
|
|
4444
|
-
created_at: change.created_at,
|
|
4445
|
-
}
|
|
4446
|
-
}
|
|
4447
|
-
|
|
4448
|
-
fn changelog_tombstone_changes(config: StorageBenchConfig) -> Vec<MaterializedChange> {
|
|
4449
|
-
changelog_materialized_changes(config)
|
|
4450
|
-
.into_iter()
|
|
4451
|
-
.map(|mut change| {
|
|
4452
|
-
change.snapshot_content = None;
|
|
4453
|
-
change.metadata = None;
|
|
4454
|
-
change
|
|
4455
|
-
})
|
|
4456
|
-
.collect()
|
|
4457
|
-
}
|
|
4458
|
-
|
|
4459
|
-
fn changelog_metadata_changes(config: StorageBenchConfig) -> Vec<MaterializedChange> {
|
|
4460
|
-
changelog_materialized_changes(config)
|
|
4461
|
-
.into_iter()
|
|
4462
|
-
.enumerate()
|
|
4463
|
-
.map(|(index, mut change)| {
|
|
4464
|
-
change.metadata = Some(snapshot_metadata(index, config.state_payload_bytes));
|
|
4465
|
-
change
|
|
4466
|
-
})
|
|
4467
|
-
.collect()
|
|
4468
|
-
}
|
|
4469
|
-
|
|
4470
|
-
fn changelog_shared_payload_changes(config: StorageBenchConfig) -> Vec<MaterializedChange> {
|
|
4471
|
-
let shared_snapshot_content = snapshot_content(0, config.state_payload_bytes);
|
|
4472
|
-
changelog_materialized_changes(config)
|
|
4473
|
-
.into_iter()
|
|
4474
|
-
.map(|mut change| {
|
|
4475
|
-
change.snapshot_content = Some(shared_snapshot_content.clone());
|
|
4476
|
-
change
|
|
4477
|
-
})
|
|
4478
|
-
.collect()
|
|
4479
|
-
}
|
|
4480
|
-
|
|
4481
|
-
fn changelog_shared_metadata_changes(config: StorageBenchConfig) -> Vec<MaterializedChange> {
|
|
4482
|
-
let shared_metadata = snapshot_metadata(0, config.state_payload_bytes);
|
|
4483
|
-
changelog_materialized_changes(config)
|
|
4484
|
-
.into_iter()
|
|
4485
|
-
.map(|mut change| {
|
|
4486
|
-
change.snapshot_content = None;
|
|
4487
|
-
change.metadata = Some(shared_metadata.clone());
|
|
4488
|
-
change
|
|
4489
|
-
})
|
|
4490
|
-
.collect()
|
|
4491
|
-
}
|
|
4492
|
-
|
|
4493
|
-
fn changelog_shared_payload_and_metadata_changes(
|
|
4494
|
-
config: StorageBenchConfig,
|
|
4495
|
-
) -> Vec<MaterializedChange> {
|
|
4496
|
-
let shared_snapshot_content = snapshot_content(0, config.state_payload_bytes);
|
|
4497
|
-
let shared_metadata = snapshot_metadata(1, config.state_payload_bytes);
|
|
4498
|
-
changelog_materialized_changes(config)
|
|
4499
|
-
.into_iter()
|
|
4500
|
-
.map(|mut change| {
|
|
4501
|
-
change.snapshot_content = Some(shared_snapshot_content.clone());
|
|
4502
|
-
change.metadata = Some(shared_metadata.clone());
|
|
4503
|
-
change
|
|
4504
|
-
})
|
|
4505
|
-
.collect()
|
|
4506
|
-
}
|
|
4507
|
-
|
|
4508
|
-
fn changelog_composite_entity_id_changes(config: StorageBenchConfig) -> Vec<MaterializedChange> {
|
|
4509
|
-
changelog_materialized_changes(config)
|
|
4510
|
-
.into_iter()
|
|
4511
|
-
.enumerate()
|
|
4512
|
-
.map(|(index, mut change)| {
|
|
4513
|
-
change.entity_id = EntityIdentity {
|
|
4514
|
-
parts: vec![
|
|
4515
|
-
entity_id("change-composite", index, config.key_pattern),
|
|
4516
|
-
index.to_string(),
|
|
4517
|
-
(index % 2 == 0).to_string(),
|
|
4518
|
-
],
|
|
4519
|
-
};
|
|
4520
|
-
change
|
|
4521
|
-
})
|
|
4522
|
-
.collect()
|
|
4523
|
-
}
|
|
4524
|
-
|
|
4525
|
-
fn changelog_selective_changes(config: StorageBenchConfig) -> Vec<MaterializedChange> {
|
|
4526
|
-
changelog_materialized_changes(config)
|
|
4527
|
-
.into_iter()
|
|
4528
|
-
.enumerate()
|
|
4529
|
-
.map(|(index, mut change)| {
|
|
4530
|
-
change.schema_key = changelog_schema_key(index, config.selectivity);
|
|
4531
|
-
change
|
|
4532
|
-
})
|
|
4533
|
-
.collect()
|
|
4534
|
-
}
|
|
4535
|
-
|
|
4536
|
-
fn changelog_entity_history_changes(config: StorageBenchConfig) -> Vec<MaterializedChange> {
|
|
4537
|
-
changelog_materialized_changes(config)
|
|
4538
|
-
.into_iter()
|
|
4539
|
-
.enumerate()
|
|
4540
|
-
.map(|(index, mut change)| {
|
|
4541
|
-
if index % 10 == 0 {
|
|
4542
|
-
change.entity_id = EntityIdentity::single(CHANGELOG_HISTORY_ENTITY_ID);
|
|
4543
|
-
}
|
|
4544
|
-
change
|
|
4545
|
-
})
|
|
4546
|
-
.collect()
|
|
4547
|
-
}
|
|
4548
|
-
|
|
4549
|
-
fn tracked_schema_key(index: usize, selectivity: StorageBenchSelectivity) -> String {
|
|
4550
|
-
if selectivity.matches(index) {
|
|
4551
|
-
TRACKED_MATCH_SCHEMA_KEY
|
|
4552
|
-
} else {
|
|
4553
|
-
TRACKED_OTHER_SCHEMA_KEY
|
|
4554
|
-
}
|
|
4555
|
-
.to_string()
|
|
4556
|
-
}
|
|
4557
|
-
|
|
4558
|
-
fn untracked_schema_key(index: usize, selectivity: StorageBenchSelectivity) -> String {
|
|
4559
|
-
if selectivity.matches(index) {
|
|
4560
|
-
UNTRACKED_MATCH_SCHEMA_KEY
|
|
4561
|
-
} else {
|
|
4562
|
-
UNTRACKED_OTHER_SCHEMA_KEY
|
|
4563
|
-
}
|
|
4564
|
-
.to_string()
|
|
4565
|
-
}
|
|
4566
|
-
|
|
4567
|
-
fn changelog_schema_key(index: usize, selectivity: StorageBenchSelectivity) -> String {
|
|
4568
|
-
if selectivity.matches(index) {
|
|
4569
|
-
CHANGELOG_MATCH_SCHEMA_KEY
|
|
4570
|
-
} else {
|
|
4571
|
-
CHANGELOG_OTHER_SCHEMA_KEY
|
|
4572
|
-
}
|
|
4573
|
-
.to_string()
|
|
4574
|
-
}
|
|
4575
|
-
|
|
4576
|
-
fn entity_id(prefix: &str, index: usize, key_pattern: StorageBenchKeyPattern) -> String {
|
|
4577
|
-
match key_pattern {
|
|
4578
|
-
StorageBenchKeyPattern::Sequential => format!("{prefix}-{index}"),
|
|
4579
|
-
StorageBenchKeyPattern::Random => format!("{prefix}-{:016x}", randomish_index(index)),
|
|
4580
|
-
}
|
|
4581
|
-
}
|
|
4582
|
-
|
|
4583
|
-
fn randomish_index(index: usize) -> u64 {
|
|
4584
|
-
let mut value = index as u64;
|
|
4585
|
-
value ^= value >> 30;
|
|
4586
|
-
value = value.wrapping_mul(0xbf58_476d_1ce4_e5b9);
|
|
4587
|
-
value ^= value >> 27;
|
|
4588
|
-
value = value.wrapping_mul(0x94d0_49bb_1331_11eb);
|
|
4589
|
-
value ^ (value >> 31)
|
|
4590
|
-
}
|
|
4591
|
-
|
|
4592
|
-
fn binary_file_ids(rows: usize) -> Vec<String> {
|
|
4593
|
-
(0..rows)
|
|
4594
|
-
.map(|index| format!("bench-file-{index}"))
|
|
4595
|
-
.collect()
|
|
4596
|
-
}
|
|
4597
|
-
|
|
4598
|
-
fn binary_payloads(rows: usize, blob_bytes: usize) -> Vec<Vec<u8>> {
|
|
4599
|
-
(0..rows)
|
|
4600
|
-
.map(|index| binary_payload(index, blob_bytes))
|
|
4601
|
-
.collect()
|
|
4602
|
-
}
|
|
4603
|
-
|
|
4604
|
-
fn binary_half_duplicate_payloads(rows: usize, blob_bytes: usize) -> Vec<Vec<u8>> {
|
|
4605
|
-
(0..rows)
|
|
4606
|
-
.map(|index| {
|
|
4607
|
-
if index % 2 == 0 {
|
|
4608
|
-
binary_payload(0, blob_bytes)
|
|
4609
|
-
} else {
|
|
4610
|
-
binary_payload(index, blob_bytes)
|
|
4611
|
-
}
|
|
4612
|
-
})
|
|
4613
|
-
.collect()
|
|
4614
|
-
}
|
|
4615
|
-
|
|
4616
|
-
fn binary_blob_writes<'a>(_file_ids: &'a [String], payloads: &'a [Vec<u8>]) -> Vec<BlobWrite<'a>> {
|
|
4617
|
-
payloads
|
|
4618
|
-
.iter()
|
|
4619
|
-
.map(|payload| BlobWrite {
|
|
4620
|
-
bytes: payload.as_slice(),
|
|
4621
|
-
})
|
|
4622
|
-
.collect()
|
|
4623
|
-
}
|
|
4624
|
-
|
|
4625
|
-
fn snapshot_content(index: usize, target_bytes: usize) -> String {
|
|
4626
|
-
let mut value = serde_json::json!({
|
|
4627
|
-
"id": format!("entity-{index}"),
|
|
4628
|
-
"value": format!("value-{index}"),
|
|
4629
|
-
"index": index
|
|
4630
|
-
});
|
|
4631
|
-
pad_snapshot_content(&mut value, target_bytes);
|
|
4632
|
-
value.to_string()
|
|
4633
|
-
}
|
|
4634
|
-
|
|
4635
|
-
fn snapshot_metadata(index: usize, target_bytes: usize) -> String {
|
|
4636
|
-
snapshot_content(index, target_bytes)
|
|
4637
|
-
}
|
|
4638
|
-
|
|
4639
|
-
fn tracked_state_header_columns() -> Vec<String> {
|
|
4640
|
-
[
|
|
4641
|
-
"entity_id",
|
|
4642
|
-
"schema_key",
|
|
4643
|
-
"file_id",
|
|
4644
|
-
"metadata",
|
|
4645
|
-
"created_at",
|
|
4646
|
-
"updated_at",
|
|
4647
|
-
"change_id",
|
|
4648
|
-
"commit_id",
|
|
4649
|
-
]
|
|
4650
|
-
.into_iter()
|
|
4651
|
-
.map(str::to_string)
|
|
4652
|
-
.collect()
|
|
4653
|
-
}
|
|
4654
|
-
|
|
4655
|
-
fn untracked_state_header_columns() -> Vec<String> {
|
|
4656
|
-
[
|
|
4657
|
-
"entity_id",
|
|
4658
|
-
"schema_key",
|
|
4659
|
-
"file_id",
|
|
4660
|
-
"metadata",
|
|
4661
|
-
"created_at",
|
|
4662
|
-
"updated_at",
|
|
4663
|
-
"global",
|
|
4664
|
-
"version_id",
|
|
4665
|
-
]
|
|
4666
|
-
.into_iter()
|
|
4667
|
-
.map(str::to_string)
|
|
4668
|
-
.collect()
|
|
4669
|
-
}
|
|
4670
|
-
|
|
4671
|
-
fn updated_snapshot_content(index: usize, target_bytes: usize) -> String {
|
|
4672
|
-
let mut value = serde_json::json!({
|
|
4673
|
-
"id": format!("entity-{index}"),
|
|
4674
|
-
"value": format!("updated-{index}"),
|
|
4675
|
-
"index": index
|
|
4676
|
-
});
|
|
4677
|
-
pad_snapshot_content(&mut value, target_bytes);
|
|
4678
|
-
value.to_string()
|
|
4679
|
-
}
|
|
4680
|
-
|
|
4681
|
-
fn partial_updated_snapshot_content(index: usize, target_bytes: usize) -> String {
|
|
4682
|
-
let mut value = serde_json::json!({
|
|
4683
|
-
"id": format!("entity-{index}"),
|
|
4684
|
-
"value": format!("value-{index}"),
|
|
4685
|
-
"index": index,
|
|
4686
|
-
"done": true
|
|
4687
|
-
});
|
|
4688
|
-
pad_snapshot_content(&mut value, target_bytes);
|
|
4689
|
-
value.to_string()
|
|
4690
|
-
}
|
|
4691
|
-
|
|
4692
|
-
fn delta_chain_snapshot_content(
|
|
4693
|
-
delta_index: usize,
|
|
4694
|
-
row_index: usize,
|
|
4695
|
-
target_bytes: usize,
|
|
4696
|
-
) -> String {
|
|
4697
|
-
let mut value = serde_json::json!({
|
|
4698
|
-
"id": format!("entity-{row_index}"),
|
|
4699
|
-
"value": format!("delta-{delta_index}-{row_index}"),
|
|
4700
|
-
"index": row_index,
|
|
4701
|
-
"delta": delta_index
|
|
4702
|
-
});
|
|
4703
|
-
pad_snapshot_content(&mut value, target_bytes);
|
|
4704
|
-
value.to_string()
|
|
4705
|
-
}
|
|
4706
|
-
|
|
4707
|
-
fn pad_snapshot_content(value: &mut serde_json::Value, target_bytes: usize) {
|
|
4708
|
-
let current = value.to_string().len();
|
|
4709
|
-
if target_bytes <= current {
|
|
4710
|
-
return;
|
|
4711
|
-
}
|
|
4712
|
-
value["padding"] = serde_json::Value::String("x".repeat(target_bytes - current));
|
|
4713
|
-
}
|
|
4714
|
-
|
|
4715
|
-
fn timestamp(index: usize) -> String {
|
|
4716
|
-
format!(
|
|
4717
|
-
"2026-05-01T00:{:02}:{:02}.000Z",
|
|
4718
|
-
(index / 60) % 60,
|
|
4719
|
-
index % 60
|
|
4720
|
-
)
|
|
4721
|
-
}
|
|
4722
|
-
|
|
4723
|
-
fn binary_payload(index: usize, len: usize) -> Vec<u8> {
|
|
4724
|
-
let mut payload = (0..len)
|
|
4725
|
-
.map(|offset| {
|
|
4726
|
-
((index as u64)
|
|
4727
|
-
.wrapping_mul(31)
|
|
4728
|
-
.wrapping_add((offset as u64).wrapping_mul(17))
|
|
4729
|
-
& 0xff) as u8
|
|
4730
|
-
})
|
|
4731
|
-
.collect::<Vec<_>>();
|
|
4732
|
-
for (offset, byte) in (index as u64).to_le_bytes().into_iter().enumerate() {
|
|
4733
|
-
if offset < payload.len() {
|
|
4734
|
-
payload[offset] = byte;
|
|
4735
|
-
}
|
|
4736
|
-
}
|
|
4737
|
-
payload
|
|
4738
|
-
}
|
|
4739
|
-
|
|
4740
|
-
fn json_documents(shape: JsonStorePayloadShape, rows: usize) -> Vec<Vec<u8>> {
|
|
4741
|
-
(0..rows).map(|index| json_document(shape, index)).collect()
|
|
4742
|
-
}
|
|
4743
|
-
|
|
4744
|
-
fn json_document(shape: JsonStorePayloadShape, index: usize) -> Vec<u8> {
|
|
4745
|
-
match shape {
|
|
4746
|
-
JsonStorePayloadShape::SmallRaw1k => json_object_document(index, 1_024, 8),
|
|
4747
|
-
JsonStorePayloadShape::MediumStructured16k => json_object_document(index, 16 * 1024, 128),
|
|
4748
|
-
JsonStorePayloadShape::LargeStructured128k => {
|
|
4749
|
-
json_object_document(index, 128 * 1024, 1_000)
|
|
4750
|
-
}
|
|
4751
|
-
JsonStorePayloadShape::LargeArray128k => json_array_document(index, 128 * 1024, 1_000),
|
|
4752
|
-
}
|
|
4753
|
-
}
|
|
4754
|
-
|
|
4755
|
-
fn updated_json_document(shape: JsonStorePayloadShape, index: usize) -> Vec<u8> {
|
|
4756
|
-
let bytes = json_document(shape, index);
|
|
4757
|
-
let mut value: serde_json::Value =
|
|
4758
|
-
serde_json::from_slice(&bytes).expect("storage bench JSON document should parse");
|
|
4759
|
-
match shape {
|
|
4760
|
-
JsonStorePayloadShape::LargeArray128k => {
|
|
4761
|
-
value["items"][999]["value"] =
|
|
4762
|
-
serde_json::Value::String(format!("updated-array-value-{index}"));
|
|
4763
|
-
}
|
|
4764
|
-
JsonStorePayloadShape::SmallRaw1k
|
|
4765
|
-
| JsonStorePayloadShape::MediumStructured16k
|
|
4766
|
-
| JsonStorePayloadShape::LargeStructured128k => {
|
|
4767
|
-
value["field_999"] = serde_json::Value::String(format!("updated-object-value-{index}"));
|
|
4768
|
-
}
|
|
4769
|
-
}
|
|
4770
|
-
serde_json::to_vec(&value).expect("storage bench updated JSON should serialize")
|
|
4771
|
-
}
|
|
4772
|
-
|
|
4773
|
-
fn json_object_document(index: usize, target_bytes: usize, fields: usize) -> Vec<u8> {
|
|
4774
|
-
let mut object = serde_json::Map::new();
|
|
4775
|
-
object.insert(
|
|
4776
|
-
"id".to_string(),
|
|
4777
|
-
serde_json::Value::String(format!("json-{index}")),
|
|
4778
|
-
);
|
|
4779
|
-
object.insert(
|
|
4780
|
-
"target".to_string(),
|
|
4781
|
-
serde_json::Value::String(format!("target-{index}")),
|
|
4782
|
-
);
|
|
4783
|
-
object.insert(
|
|
4784
|
-
"status".to_string(),
|
|
4785
|
-
serde_json::Value::String(if index % 2 == 0 { "open" } else { "closed" }.to_string()),
|
|
4786
|
-
);
|
|
4787
|
-
object.insert(
|
|
4788
|
-
"nested".to_string(),
|
|
4789
|
-
serde_json::json!({
|
|
4790
|
-
"target": format!("nested-target-{index}"),
|
|
4791
|
-
"revision": index,
|
|
4792
|
-
}),
|
|
4793
|
-
);
|
|
4794
|
-
for field_index in 0..fields {
|
|
4795
|
-
object.insert(
|
|
4796
|
-
format!("field_{field_index}"),
|
|
4797
|
-
serde_json::Value::String(format!("value-{index}-{field_index}")),
|
|
4798
|
-
);
|
|
4799
|
-
}
|
|
4800
|
-
pad_json_object(&mut object, target_bytes);
|
|
4801
|
-
serde_json::to_vec(&serde_json::Value::Object(object))
|
|
4802
|
-
.expect("storage bench object JSON should serialize")
|
|
4803
|
-
}
|
|
4804
|
-
|
|
4805
|
-
fn json_array_document(index: usize, target_bytes: usize, items: usize) -> Vec<u8> {
|
|
4806
|
-
let mut object = serde_json::Map::new();
|
|
4807
|
-
object.insert(
|
|
4808
|
-
"id".to_string(),
|
|
4809
|
-
serde_json::Value::String(format!("json-array-{index}")),
|
|
4810
|
-
);
|
|
4811
|
-
object.insert(
|
|
4812
|
-
"target".to_string(),
|
|
4813
|
-
serde_json::Value::String(format!("target-{index}")),
|
|
4814
|
-
);
|
|
4815
|
-
object.insert(
|
|
4816
|
-
"status".to_string(),
|
|
4817
|
-
serde_json::Value::String(if index % 2 == 0 { "open" } else { "closed" }.to_string()),
|
|
4818
|
-
);
|
|
4819
|
-
object.insert(
|
|
4820
|
-
"items".to_string(),
|
|
4821
|
-
serde_json::Value::Array(
|
|
4822
|
-
(0..items)
|
|
4823
|
-
.map(|item_index| {
|
|
4824
|
-
serde_json::json!({
|
|
4825
|
-
"index": item_index,
|
|
4826
|
-
"status": if item_index % 2 == 0 { "ready" } else { "blocked" },
|
|
4827
|
-
"value": format!("item-{index}-{item_index}"),
|
|
4828
|
-
})
|
|
4829
|
-
})
|
|
4830
|
-
.collect(),
|
|
4831
|
-
),
|
|
4832
|
-
);
|
|
4833
|
-
pad_json_object(&mut object, target_bytes);
|
|
4834
|
-
serde_json::to_vec(&serde_json::Value::Object(object))
|
|
4835
|
-
.expect("storage bench array JSON should serialize")
|
|
4836
|
-
}
|
|
4837
|
-
|
|
4838
|
-
fn pad_json_object(object: &mut serde_json::Map<String, serde_json::Value>, target_bytes: usize) {
|
|
4839
|
-
let current = serde_json::to_vec(&serde_json::Value::Object(object.clone()))
|
|
4840
|
-
.expect("storage bench JSON should serialize")
|
|
4841
|
-
.len();
|
|
4842
|
-
if target_bytes <= current {
|
|
4843
|
-
return;
|
|
4844
|
-
}
|
|
4845
|
-
object.insert(
|
|
4846
|
-
"padding".to_string(),
|
|
4847
|
-
serde_json::Value::String("x".repeat(target_bytes - current)),
|
|
4848
|
-
);
|
|
4849
|
-
}
|
|
4850
|
-
|
|
4851
|
-
fn json_projection_paths(projection: JsonStoreProjectionShape) -> Vec<JsonProjectionPath> {
|
|
4852
|
-
match projection {
|
|
4853
|
-
JsonStoreProjectionShape::TopLevelTarget => vec![JsonProjectionPath::new("/target")],
|
|
4854
|
-
JsonStoreProjectionShape::TopLevelTenProps => (0..10)
|
|
4855
|
-
.map(|index| JsonProjectionPath::new(format!("/field_{index}")))
|
|
4856
|
-
.collect(),
|
|
4857
|
-
JsonStoreProjectionShape::NestedTarget => vec![JsonProjectionPath::new("/nested/target")],
|
|
4858
|
-
JsonStoreProjectionShape::ArrayItem999 => {
|
|
4859
|
-
vec![JsonProjectionPath::new("/items/999/value")]
|
|
4860
|
-
}
|
|
4861
|
-
JsonStoreProjectionShape::Status => vec![JsonProjectionPath::new("/status")],
|
|
4862
|
-
}
|
|
4863
|
-
}
|