You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: apps/nextra/pages/en/build/smart-contracts/maps.mdx
+35-6
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ Breaking down the gas costs further, we have:
16
16
2. IO gas costs —generally much lower— which depend on the number and size of resources read and modified.
17
17
3. execution gas costs are based on the computation needed, and are generally in the similar scale as io gas costs.
18
18
19
-
Transactions that modify the same **slot** cannot be executed in parallel (with some exceptions, like aggregators and resources as a part of the same resource group), as they conflict with one another.
19
+
Transactions that modify the same **slot** cannot be executed concurrently (with some exceptions, like aggregators and resources as a part of the same resource group), as they conflict with one another.
20
20
21
21
One useful analogy is thinking about each **slot** being a file on a disk,
22
22
then performance of smart contract would correlate well to a program that
@@ -27,9 +27,9 @@ operates on files in the same way.
|`OrderedMap`| Bounded (fits in a single **slot**) | Stored entirely within the resource that contains it | Supports ordered access (front/back, prev/next), implemented as sorted vector, but operations are effectively O(log(n)) due to internal optimizations |
30
-
|`Table`| Unbounded | Each (key, value) stored in a separate **slot**| Supports basic operations, like `add`, `remove`, `contains`, but **not iteration**, and **cannot be destroyed**; useful for large/unbounded keys/values and high-parallelism cases|
31
-
|`TableWithLength`| Unbounded | same as `Table`| Variant of `Table`, with additional length tracking, which adds `length`, `empty`, and `destroy_empty` methods; Adding or removing elements **cannot** be done in parallel, modifying existing elements can. |
32
-
|`BigOrderedMap`| Unbounded | Combines multiple keys into a single **slot**, initially stored within resource that contains it, and grows into multiple **slots** dynamically | Implemented as B+ tree; **opportunistically parallel** for non-adjacent keys; supports ordered access (front/back, prev/next); configurable node capacities to balance storage and performance |
30
+
|`Table`| Unbounded | Each (key, value) stored in a separate **slot**| Supports basic operations, like `add`, `remove`, `contains`, but **not iteration**, and **cannot be destroyed**; useful for large/unbounded keys/values and where high-concurrency is needed|
31
+
|`TableWithLength`| Unbounded | same as `Table`| Variant of `Table`, with additional length tracking, which adds `length`, `empty`, and `destroy_empty` methods; Adding or removing elements **cannot** be done concurrently, modifying existing elements can. |
32
+
|`BigOrderedMap`| Unbounded | Combines multiple keys into a single **slot**, initially stored within resource that contains it, and grows into multiple **slots** dynamically | Implemented as B+ tree; **opportunistically concurrent** for non-adjacent keys; supports ordered access (front/back, prev/next); configurable node capacities to balance storage and performance |
33
33
34
34
Note:
35
35
-`SimpleMap` has been deprecated, and replaced with `OrderedMap`.
@@ -39,7 +39,7 @@ Note:
39
39
40
40
We measured performance at small scale, measuring microseconds taken for a single pair of `insert` + `remove` operation, into a map of varied size.
41
41
42
-
| num elements | OrderedMap | BigOrderedMap all inlined| BigOrderedMap max_degree=16 |
42
+
| num elements | OrderedMap | BigOrderedMap max_degree>10000| BigOrderedMap max_degree=16 |
@@ -140,11 +140,16 @@ Its current implementation is B+ tree, which is chosen as it is best suited for
140
140
Implementation has few characteristics that make it very versatile and useful across wide range of usecases:
141
141
142
142
- When it has few elements, it stores all of them within the resource that contains it, providing comparable performance to OrderedMap itself, while then dynamically growing to multiple resources as more and more elements are added
143
-
- It reduces amount of conflicts: modifications to a different part of the key-space are generally parallel, and it provides knobs for tuning between parallelism and size
143
+
- It reduces amount of conflicts: modifications to a different part of the key-space can be generally done concurrently, and it provides knobs for tuning between concurrency and size
144
144
- All operations have guaranteed upper-bounds on performance (how long they take, as well as how much execution and io gas they consume), allowing for safe usage across a variety of use cases.
145
145
- One caveat, is refundable storage fee. By default, operation that requires map to grow to more resources needs to pay for storage fee for it. Implementation here has an option to pre-pay for storage slots, and to reuse them as elements are added/removed, allowing applications to achieve fully predictable overall gas charges, if needed.
146
146
- If key/value is within the size limits map was configured with, inserts will never fail unpredictably, as map internally understands and manages maximal **slot** size limits.
147
147
148
+
### `BigOrderedMap` structure
149
+
150
+
`BigOrderedMap` is represented as a tree, where inner nodes split the "key-space" into separate ranges for each of it's children, and leaf nodes contain the actual key-value pairs.
151
+
Internally it has `inner_max_degree` representing largest number of children an inner node can have, and `leaf_max_degree` representing largest number of key-value pairs leaf node can have.
152
+
148
153
#### Creating `BigOrderedMap`
149
154
150
155
Because it's layout affects what can be inserted and performance, there are a few ways to create and configure it:
@@ -166,3 +171,27 @@ Because it's layout affects what can be inserted and performance, there are a fe
The Smart Table is a scalable hash table implementation based on linear hashing.
178
+
This data structure aims to optimize storage and performance by utilizing linear hashing, which splits one bucket at a time instead of doubling the number of buckets, thus avoiding unexpected gas costs.
179
+
Unfortunatelly, it's implementation makes every addition/removal be a conflict, making such transactions fully sequential.
180
+
The Smart Table uses the SipHash function for faster hash computations while tolerating collisions. Unfortunatelly, this also means that collisions are predictable, which means that if end users can control the keys being inserted, it can have large number of collisions in a single bucket.
181
+
182
+
### SmartTable Structure
183
+
184
+
The `SmartTable` struct is designed to handle dynamic data efficiently:
185
+
186
+
-`buckets`: A table with a length that stores vectors of entries.
187
+
-`num_buckets`: The current number of buckets.
188
+
-`level`: The number of bits representing `num_buckets`.
189
+
-`size`: The total number of items in the table.
190
+
-`split_load_threshold`: The load threshold percentage that triggers bucket splits.
191
+
-`target_bucket_size`: The target size of each bucket, which is not strictly enforced.
0 commit comments