Scalability Analysis of user.SetMetadata on AVL_backed State
TL;DR
- The
SetMetadataexecution succeeded atN=10,000andN=100,000. - At
N=1,000,000, execution did not reach the main measurement phase and failed during the precondition setup due to abroadcast timeout. - The per-call
gas_avgandstorage_avgofSetMetadataincreased gradually. - In contrast, during precondition generation, both gas usage and wall-clock time increased steadily, with wall-clock time showing a significantly larger increase.
Conclusion:
Within the observed range, the limiting factor does not appear to be the SetMetadata call itself,
but rather the overhead of broadcast and execution time in the large-scale precondition generation phase.
Structurally, as the number of users increases, the system exhibits a pattern of gradual cost accumulation.
It is therefore more appropriate to interpret this as a system where
the overall write path cost increases continuously over a large global user state.
The full dataset is available here:
Structure Overview
SetMetadata operates on the following structure:
- Outer:
AVL(address -> value) - Inner value:
map[string]string
Execution flow:
- Lookup
address -> metadata mapfrom the AVL structure - Update key/value inside the metadata map
- Persist the updated map along with related objects
Important:
In this experiment, N refers to the number of users, not the number of metadata keys.
In other words, this experiment observes:
- Not the growth of metadata map size
- But the cost impact of expanding the user index AVL
Experimental Setup
- Environment: custom-built
gnodev - Branch:
dev/jae/gas-model-improvements - Commit:
2d507b86935576c6eb5b06cae3b14861f0090c87
Results (Milestones)
| N | Status | Result |
|---|---|---|
| 10,000 | Success | gas_avg=4,439,895, storage_avg=28,270, elapsed_sec=2.035 |
| 100,000 | Success | gas_avg=4,624,762, storage_avg=28,410, elapsed_sec=2.044 |
| 1,000,000 | Failed | broadcast timeout during setup |
Key point:
The current limitation appears not in the SetMetadata call itself,
but in the precondition generation phase.
Key Observations
1. Per-call cost remains relatively stable
gas_avg:4.43M → 4.62Mstorage_avg:28,270 → 28,410
→ Increasing the number of users does not significantly increase per-call cost.
2. Precondition cost increases significantly
gas_per_item: ~3x increasestorage_per_item: relatively stableelapsed_sec: ~15x increase
→ The most notable signal is the increase in execution time
3. Bottleneck appears in precondition, not execution
Failure point:
SetMetadatacall ❌- user creation batch (
broadcast) ⭕
→ The current issue is closer to:
“building large-scale state” rather than the write operation itself
Precondition Trend
- Gas and wall-clock time increase steadily
- Storage remains relatively stable
→ Indicates a cumulative cost pattern even with fixed batch size
Estimated Store Operations per Call
Static estimate (not based on VM instrumentation)
StoreGetObject:[hypothesis] 4..7StoreSetObject:[hypothesis] 4..7
Rationale
SetMetadata involves:
- AVL lookup (user index)
- Metadata map loading
- Map update
- Object persistence
- Dirty object propagation
Each step may trigger:
StoreGetObjectStoreSetObject
Why range-based estimation
Actual counts may vary depending on:
- Cold vs warm access
- Existing vs new key
- Owner chain depth
- Internal branching logic
→ Therefore, these values should be interpreted as
approximate indicators of access scale, not exact measurements
Interpretation
The cost of this function depends more on:
- The size of the AVL (
address index) - Rather than the size of the metadata map itself
→ This is not primarily a map problem, but rather:
a cost issue driven by operating over a large AVL structure
Scaling Interpretation
From the observed results:
- Individual updates remain stable
- Precondition generation cost increases rapidly
This suggests a system that:
- Does not collapse abruptly
- But exhibits cumulative cost growth as scale increases
In particular:
- As the number of user entries in the AVL grows
- The overall cost of lookup and write/update paths increases together
→ The key risk is:
not the cost of a single operation,
but the accumulated cost of repeated operations over large state
Core / Dapp Implications
Dapp Perspective
SetMetadataitself remains stable- However, large-scale user setup becomes increasingly expensive
Key considerations:
- Batch size tuning
- Distributed setup strategy
- Precondition design
- Stability of long-running broadcasts
Core Perspective (Careful Interpretation)
From the current data:
- It is difficult to conclude that AVL itself is the primary bottleneck
Instead, it may be more meaningful to analyze:
- AVL lookup cost contribution
- Serialization/deserialization overhead
- Dirty propagation cost
- Batch execution overhead
→ The bottleneck likely lies not in a single structure,
but within the overall write pipeline
Suggested Directions (Non-binding)
Short-term:
- Improve precondition strategy
- Optimize batch and broadcast handling
Long-term:
- Partition global user index
- Improve write locality
- Apply lazy initialization
- Simplify index update paths
Final Conclusion
SetMetadata operates stably up to N=100,000, with no immediate OOG observed.
However:
- At
N=1,000,000, failure occurs in the precondition stage - Batch execution cost increases significantly with scale
Therefore, this result suggests that the main bottleneck is not SetMetadata itself, but the cost of building and maintaining large-scale user metadata state.