Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

statemanager: cache and other refactors #3569

Merged
merged 27 commits into from
Aug 12, 2024

Conversation

gabrocheleau
Copy link
Contributor

This reverts some of the changes from #3554 and rebuilds upon them.

Copy link

codecov bot commented Aug 9, 2024

Codecov Report

Attention: Patch coverage is 66.93227% with 83 lines in your changes missing coverage. Please review.

Project coverage is 28.94%. Comparing base (f9788a1) to head (ba00837).
Report is 1 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

Flag Coverage Δ
block 73.45% <ø> (?)
blockchain 85.02% <ø> (?)
client 0.00% <0.00%> (ø)
common 89.70% <ø> (?)
evm 63.39% <ø> (?)
genesis 0.00% <ø> (?)
statemanager 65.63% <73.75%> (-0.20%) ⬇️
trie 52.05% <ø> (?)
tx 77.77% <ø> (ø)
util 69.89% <ø> (?)
vm 58.47% <100.00%> (?)
wallet 0.00% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Copy link
Member

@holgerd77 holgerd77 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great so far! 🤩

The one major thing which I would still do structurally differently is that I think we should pass in the cache options directly to the Caches class and - for the state managers - take an initialized Caches object as the option input (and no cache options at all).

The we can remove the default initialization this._caches = new Caches(....) and go with no-cache-as-default.

Default initializations are major tree shaking killers. If we remove, a huge block of code goes away (if not used), so all caching code + the large LRU and js-sdsl dependencies.

It is a bit more to do for users on the UX side (so if caches should be used one needs to pass over: { caches: new Caches() } (or with some options, but I would think that this is very much worth it.

@gabrocheleau
Copy link
Contributor Author

Looks great so far! 🤩

The one major thing which I would still do structurally differently is that I think we should pass in the cache options directly to the Caches class and - for the state managers - take an initialized Caches object as the option input (and no cache options at all).

The we can remove the default initialization this._caches = new Caches(....) and go with no-cache-as-default.

Default initializations are major tree shaking killers. If we remove, a huge block of code goes away (if not used), so all caching code + the large LRU and js-sdsl dependencies.

It is a bit more to do for users on the UX side (so if caches should be used one needs to pass over: { caches: new Caches() } (or with some options, but I would think that this is very much worth it.

Just did that!

It did involve some other changes, notably in tests and in the default VM.create() state manager instantiation. I have decided to default to using Caches() (so, same behavior as before) for the default VM as a lot of vm packages tests seem to rely on that.

@gabrocheleau gabrocheleau changed the title statemanager: rework capabilities refactoring statemanager: cache and other refactors Aug 9, 2024
@gabrocheleau
Copy link
Contributor Author

Made some more progess with making cache optional and fixing tests where necessary.

With regards to your comment:
"I think you can likely simplify many of the above if-causes in a same manner and simply remove." (link)

I'm actually having a broader reflection about the handling of the undefined caches. I'm not a fan of the complex if clauses at the moment, I think the dual checking of undefined and deactivate is confusing.

I don't have a clear full picture right now. We currently instantiate each cache (account, storage, code) with defaults, unless deactivate has been set to true. Now since _caches itself is optional, and all caches are optional on their own, I don't think it's necessary to check against deactivate in usage as we are doing here. Perhaps we still need to keep deactivate as a CacheStateManagerOption, but I think we could/should refrain from using it to check whether or not a particular cache is active.

@acolytec3
Copy link
Contributor

Made some more progess with making cache optional and fixing tests where necessary.

With regards to your comment: "I think you can likely simplify many of the above if-causes in a same manner and simply remove." (link)

I'm actually having a broader reflection about the handling of the undefined caches. I'm not a fan of the complex if clauses at the moment, I think the dual checking of undefined and deactivate is confusing.

I don't have a clear full picture right now. We currently instantiate each cache (account, storage, code) with defaults, unless deactivate has been set to true. Now since _caches itself is optional, and all caches are optional on their own, I don't think it's necessary to check against deactivate in usage as we are doing here. Perhaps we still need to keep deactivate as a CacheStateManagerOption, but I think we could/should refrain from using it to check whether or not a particular cache is active.

If the caches are optional, can't you just do

this.account?.del(key)
this.storage?.del(key)
this.storage?.get(key)

@gabrocheleau
Copy link
Contributor Author

Made some more progess with making cache optional and fixing tests where necessary.
With regards to your comment: "I think you can likely simplify many of the above if-causes in a same manner and simply remove." (link)
I'm actually having a broader reflection about the handling of the undefined caches. I'm not a fan of the complex if clauses at the moment, I think the dual checking of undefined and deactivate is confusing.
I don't have a clear full picture right now. We currently instantiate each cache (account, storage, code) with defaults, unless deactivate has been set to true. Now since _caches itself is optional, and all caches are optional on their own, I don't think it's necessary to check against deactivate in usage as we are doing here. Perhaps we still need to keep deactivate as a CacheStateManagerOption, but I think we could/should refrain from using it to check whether or not a particular cache is active.

If the caches are optional, can't you just do

this.account?.del(key)
this.storage?.del(key)
this.storage?.get(key)

Pretty much what I have ended up doing, yes!

@holgerd77
Copy link
Member

Yes, agree

size: this.config.codeCache,
},
caches: new Caches({
accountCacheOpts: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can fully drop the CacheOpts from this key, makes it nicer to digest/read and remains fully expressive.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same for others of course)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

size: number
}

export interface CacheStateManagerOpts {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe drop the StateManager here from the name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we remove StateManager, we'll have a naming conflict with CacheOpts declared above. I am not 100% satisfied with the general naming, and there is some overlap between these interfaces/types (which makes me want to unify them somehow), but there does not seem to be sufficient overlap to really unify them. Open to suggestions!

Copy link
Member

@holgerd77 holgerd77 Aug 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe give this a second thought, but I would kill off the deactivate part and take the size === 0 as the one and only way to deactivate and then remove the CacheOpts and only use the CachesStateManagerOpts (then renamed to CacheOpts 😋) as the one thing for all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, just seeing this comment I'll give that a try, would really like to simplify further

_storageCache: StorageCache
_contractCache: Map<string, Uint8Array>

protected _accountCache: AccountCache
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The caches in RPCStateManager will still be transfered to the new interface, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The contractCache seems different in the rpcStateManager than in the others (i.e. not the ContractCache class). It would indeed be nice to refactor in a similar fashion here. @acolytec3, why do we use a custom Map<string, Uint8Array> here rather than the ContractCache class?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pretty sure that just some of the inconsistencies we have in state manager and that was rather to have some simple version in and so you can just fully and 1:1 with the original version replace.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm 99% sure that is just because the original implementation from the RPCstatemanager just didn't have caches at all. No compelling reason though and the cache will do the same thing.

Copy link
Contributor Author

@gabrocheleau gabrocheleau Aug 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just updated to use the same _caches property and type as the other 2

Copy link
Contributor

@acolytec3 acolytec3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. One TODO to be cleaned up separately

@acolytec3 acolytec3 merged commit 45e0a6d into master Aug 12, 2024
34 checks passed
@acolytec3 acolytec3 deleted the statemanager/capabilities-refactor branch August 12, 2024 16:07
@holgerd77
Copy link
Member

🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants