-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Optmize GetLatestStateHeight calls #3817
Comments
How exactly are you doing these calls? The only case where |
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 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. func (s *Server) getHistoricParams(reqParams params.Params) (uint32, *neorpc.Error) {
if s.chain.GetConfig().Ledger.KeepOnlyLatestState {
return 0, neorpc.WrapErrorWithData(neorpc.ErrUnsupportedState, fmt.Sprintf("only latest state is supported: %s", errKeepOnlyLatestState))
}
if len(reqParams) < 1 {
return 0, neorpc.ErrInvalidParams
}
height, respErr := s.blockHeightFromParam(reqParams.Value(0))
if respErr != nil {
hash, err := reqParams.Value(0).GetUint256()
if err != nil {
return 0, neorpc.NewInvalidParamsError(fmt.Sprintf("invalid block hash or index or stateroot hash: %s", err))
}
b, err := s.chain.GetBlock(hash)
if err != nil {
stateH, err := s.chain.GetStateModule().GetLatestStateHeight(hash) <----- HERE
if err != nil {
return 0, neorpc.NewInvalidParamsError(fmt.Sprintf("unknown block or stateroot: %s", err))
}
height = stateH
} else {
height = b.Index
}
}
return height + 1, nil
} |
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. |
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 |
I doubt it can be solved without DB scheme change. |
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
GetLatestStateHeight
function:neo-go/pkg/core/stateroot/module.go
Line 134 in 0d8c751
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!
The text was updated successfully, but these errors were encountered: