mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2026-03-01 04:28:51 +00:00
Optmize GetLatestStateHeight calls #1486
Labels
No labels
I1
I2
I3
I4
S1
S2
S3
S4
U0
U1
U2
U3
U3
U4
blocked
bug
bug
cli
compiler
config
config
consensus
dependencies
discussion
documentation
enhancement
epic
feature
go
good first issue
help wanted
neotest
network
oracle
performance
question
rpc
security
smartcontract
task
task
task
test
vm
wallet
windows
windows
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
nspcc-dev/neo-go#1486
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @lock9 on GitHub (Feb 18, 2025).
Is your feature request related to a problem? Please describe.
We are deploying our infrastructure using Neo Go. We noticed that the historic endpoints consume a lot of CPU resources. A few calls to historic endpoints are enough to 'break' the server. Maybe it's a configuration issue, but we have requests that stay over five minutes waiting for Neo Go.
The culprit seems to be the
GetLatestStateHeightfunction:nspcc-dev/neo-go@0d8c751e50/pkg/core/stateroot/module.go (L134)Describe the solution you'd like
Create a prefix to map roots to heights, getting the roots directly, without using 'seek'. Adding this new information has a few downsides:
However, this would significantly speed up historical requests and prevent excessive CPU consumption. In practice, CPU usage became so intense that we struggled to connect to our VMs. IMHO, the performance improvement outweighs the minor increase in storage usage.
EDIT: Sorry for the confusion, I'm not sure if it's either height -> root or root -> height
Describe alternatives you've considered
I've tried a 'read cache', but that doesn't solve the issue. We also have an indexer being built.
Additional context
I implemented this feature in a local branch. It does improve the performance, but it's not fully tested. Maybe it doesn't work.
Don't forget to add labels!
@roman-khimov commented on GitHub (Feb 19, 2025):
How exactly are you doing these calls? The only case where
GetLatestStateHeightis invoked at all is when you're using state hash as parameter. But in fact you can use block index or block hash and avoid this function being called completely. In the vast majority of cases block indexes or hashes are more available to users than state root hashes.@lock9 commented on GitHub (Feb 19, 2025):
We use it to get historical balances (most times). In fact, what you said is very relevant, becaus it was a bug in the frontend that was sending incorrect parameters (root hash). This was making code fall into the
GetLatestStateHeightbranch. This may explain why caching wasn't working as expected.The 'problem' with this code, is that a few requests is enough to consume all the CPU available. Are these extra branches necessary? (accept the height only instead of the root)
I know that the current code was querying for the state root, and then making the historic call. If I understand correctly, the first step is skippable.
@roman-khimov commented on GitHub (Feb 19, 2025):
Yes because we always wanted to give more options to users. Therefore we support block numbers, block hashes and state root hashes as parameters for historic calls.
Now if that's really problematic wrt resource use we may think of omitting state root hash support, although it's somewhat natural for state-related queries.
That's exactly what I'm trying to convey, in many cases you don't need state root hash itself.
@lock9 commented on GitHub (Feb 20, 2025):
If sending an inexistent hash causes the node to read 'all the storage', it must either be optimized or disabled. The first option seems more reasonable since removing it may cause applications to break.
Do you think it's possible to optimize it without consuming more storage or using an extra write? Maybe using an in-memory bloom filter? It won't solve the issue 'permanently', but it could prevent the node from being stuck on all requests
@roman-khimov commented on GitHub (Feb 20, 2025):
I doubt it can be solved without DB scheme change.