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

WIP: cachewrap on iavl tree #17

Closed
wants to merge 3 commits into from
Closed

WIP: cachewrap on iavl tree #17

wants to merge 3 commits into from

Conversation

ethanfrey
Copy link
Contributor

To efficiently implement caching on top over iavl including with range queries, we cannot add a layer outside of iavl, but need support inside of it. This is a requirement for the rewrite of cosmos-sdk.

I implement a CachedTree that performs this task straightforward, but is not a Tree, so cannot be used interchangably. This is created with CacheWrap()

I also implement a second approach that is transparently a tree, but may have a bit too much magic under the hood for some people. This is created with Cache().

Please provide feedback on how to evolve this.

// make a shallow copy, reuse cache, etc.
func (n *nodeDB) clone() *nodeDB {
cacheDB := *n
return &cacheDB
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this safe? For example they will share a mutex now I believe, unless those are copy by value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Share mutex is a no-no.
I guess I figured the only use case was using a cache, then committing it or rolling it back before touching the parent db.

So, yeah, optimized for expected use case does make it fragile....

// and clears the cache - meant for cachedbs...
func (c *CachedTree) Write() error {
// TODO: some sort of checks and balances...
c.parent.root = c.root
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if this interacts with the version changes in the other PR. ie. if we also should set c.parent.version here.

}

// change batch on the cache...
ndb.batch = newMagicBatch(ndb.batch, t, cache)
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I feel like this is perhaps too magical/fragile, hm.... I'd prefer a solution with interfaces so we don't have to return a *Tree, or more insurance that we don't break the ndb batching here, ie. for example what if the current batch isn't empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it appends to the current batch. i think the tests cover that.

but yeah, it is my fake fix around all code using *Tree not some interface.

@ethanfrey
Copy link
Contributor Author

Thanks for the feedback. Still at a big loss how to proceed here...

@cloudhead
Copy link
Contributor

Would figuring out an interface unblock this? Then we can go with the less-magic approach.

@ethanfrey
Copy link
Contributor Author

I would still like @jaekwon to give feedback here. I know he has strong opinions on design like this.

@jaekwon
Copy link
Contributor

jaekwon commented Dec 8, 2017

Lets do the goroutine thing.

@ethanfrey
Copy link
Contributor Author

@jaekwon AFAIK there is no goroutine thing for caching. Maybe you were thinking of iteration.

We need a way to cache an Iterator. What is your opinion to this question?

@jaekwon
Copy link
Contributor

jaekwon commented Dec 10, 2017

I'll try to implement a generic CacheIterKVStore that can take iavl as is with no modification (i.e. no changes from this branch needed).

The KV part is easy (we've already written it many times before, the magic cache from sdk1, and in tmlibs.db as well), but for iteration of a CacheIterKVStore we want to create another goroutine that uses this goroutine-based iterator (link), that merges with the cached items in CacheIterKVStore.

I'll do this next.

@jaekwon
Copy link
Contributor

jaekwon commented Dec 18, 2017

Implemented in cosmos-sdk now, sdk2 branch.

@jaekwon jaekwon closed this Dec 18, 2017
@cloudhead cloudhead deleted the feature/cachewrap branch December 18, 2017 15:42
tac0turtle pushed a commit that referenced this pull request Apr 9, 2022
* Add unbounded key string to KeyFormat

* Add test vectors for unbounded length keys

* Add some notes

* update .gitignore

* Add FastNode struct

* WIP: make Get work with new FastNode

* when retrieving fastnode fails, return errors vs. panic

* add comments clarifying what index represents

* make the linter happy

* Add small tweaks to fast_node.go

* add TODO & small linter tweaks

* Update comment

* update fast node cache in set

* add debugging output when falling back to original logic

* return error instead of panic

* WIP: refactor set ops to work with fast store

* update Set of mutable tree, begin unit testing

* update GetVersioned to check fast nodes before trying the immutable

* check fast node version before nil value check in get of immutable tree

* fix small bugs and typos, continue writing unit tests for Set

* unit test saveFastNodeVersion

* simplify storing unsaved fast nodes

* resolve a bug with not writing prefix for fast node to disk

* remove fast nodes from disk on save and clear fast cache when version is deleted, fix all tests but random and with index

* resolve an issue with randomized tests caused by the fast node cache not being cleared when latest version is saved

* split unsaved fast node changes into additions and removals

* save fast node removals

* move fast node cache clearing to nodedb

* use regular logic only when fast node version is greater than immutable tree'

* clean up tree_random_test.go

* clear unsaved fast node removals on rollback

* fix randomized test failures caused by a typo in ndb DeleteVersion for loop

* implement GetFast method to preserve Get with correct index return, convert unit tests from Get to GetFast where applicable

* ensure Get and GetFast return the same values in tree_random_test.go

* test fast node cache is live in random tree tests

* improve mutable tree unit tests related to new functionality

* clean up tree_test.go

* implement GetVersionedFast to preserve the index in GetVersioned

* restore accidentally deleted test in mutable tree test

* spurious whitespace

* refactor mutable tree

* fix comment in mutable tree

* add benchmark results

* avoid redundant full tree search in GetFast of immutable tree when fast node is nil and tree is latest

* fix naming for bench test get on random keys

* use method for get latestversio in get fast

* optimize GetFast, perform a refactor to ensure that fast nodes on disk are matched and better test

* add latest bench

* Fast Node Iteration (#7)

* propagate errors from nodedb and avoid panicking

* begin implementing fast node iteration

* resolve rebase issue in random tests

* fix iteration to deserialize fast node for extracting the correct value

* finalzie iteration and let all unit tests pass

* add benchmarks

* merge GetVersioned and GetVersionedFast

* remove fast node deletion from DeleteVersion and DeleteVersionRange and benchmark

* fix and unit test iteration on mutable and immutable trees

* implement tests for iterator and iterate, begin testing fast iterator

* fix and unit test fast iterator

* refactor iterate methods of mutable and immutable trees

* resolve some warnings

* remove old bench results

* refactor bench tests for iteration

* Fast Cache Migration (#9)

* implement nodedb changes to set and get chain version from the database

* implement and unit test upgrade to fast storage in mutable tree

* refactor for auto upgrade to fast version in mutable tree contructor, load version and lazy load version

* use proper functionality for getting latest version

* remove unused error

* fix comment

* use fast version value in tests

* spurious tab

* fix style problems and remove redundant code in tests

* Rename Get to GetWithIndex and GetFast to Get

* refactor and clean up bench tests

* remove extra byte from fast node length

* clean up immutable tree

* refactor nil tree or ndb error for the iterators and their tests

* avoid exporting methods for getting unsaved additions and removals

* refactor fast upgrade to read from tree instead of traversing disk nodes and orphans, update unit tests

* remove unneeded comment

* refer to storage version consistently across the project

* fix more warnings

* optimize removal of fast nodes from cache on deletion

* small changes in teh mutable tree

* correct storage version key

* auto set fast version in SaveVersion

* avoid exporting new methods of the immutable tree

* go fmt

* Fix comment in fast iterator

Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>

* add extra comment for domain in fast iterator

Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>

* add comments for moving the iterator before the first element

* add comment for describing what mirror is in assertIterator of testutils

* fix checking the mirror for descending iterator in tests

* Update testutils_test.go with a comment

Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>

* Update benchmarks/bench_test.go with a comment for runKnownQueriesFast

Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>

* Update benchmarks/bench_test.go with a comment for runQueriesFast

Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>

* export IsFastCacheEnabled and add an assert in bench tests

* Update comment immutable_tree.go

Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>

* Update comment for migration in mutable_tree.go

Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>

* simlify Iterate in mutable tree, add debug log for

* Fast Cache - Downgrade - reupgrade protection and other improvements (#12)

* add leaf hash to fast node and unit test

* refactor get with index and get by index, fix migration in load version and lazy load version

* use Get in GetVersioned of mutable tree

* refactor non membership proof to use fast storage if available

* bench non-membership proof

* fix bench tests to work with the new changes

* add downgrade-reupgrade protection and unit test

* remove leaf hash from fast node

* resolve multithreading bug related to iterators not being closed

* clean up

* use correct tree in bench tests

* add cache to tree used to bench non membership proofs

* add benc tests for GetWithIndex and GetByIndex

* revert GetWithIndex and GetByIndex

* remove unused import

* unit test re-upgrade protection and fix small issues

* remove redundant setStorageVersion method

* fix bug with appending to live stage version to storage version and nit test

* add comment for setFastStorageVersionToBatch

* refactor and improve unit tests for reupgrade protection

* rename ndb's isFastStorageEnabled to hasUpgradedToFastStorage and add comments

* comment out new implementation for GetNonMembershipProof

* update comments in nodedb to reflect the difference between hasUpgradedToFastStorage and shouldForceFastStorageUpdate

* refactor nodedb tests

* downgrade tendermint to 0.34.14 - osmosis's latest cosmos sdk does not support 0.35.0

* fix bug where fast storage was not enabled when version 0 was attempted to be loaded

* implement unsaved fast iterator to be used in mutable tree (#16)

* address comments from unsaved fast iterator PR

* expose isUpgradeable method on mutable tree and unit test (#17)

* expose isUpgradeable method on mutable tree and unit test

* go fmt

* resolve problems with rebasing

* update CHANGELOG.md

* tendermint v0.35.0

* fix String() bench

* fix duplication lint in iterator_test.go

* fix lint for tree.ndb.DeleteFastNode error return not checked

* fix Error return value of `ndb.resetBatch` is not checked

* fix Error return value of `ndb.traversePrefix` is not checked

* fix Error: struct of size 64 bytes could be of size 56 bytes

* fix Error: `comitted` is a misspelling of `committed`

* fix issues in basic_test.go

* address comments in fast_iterator.go

* address comments in immutable tree

* address comments in iterator.go

* address comments in key_format.go

* address remaining comments

* fix Error: Error return value of `ndb.batch.Write` is not checked

* fix Error: receiver name t should be consistent with previous receiver name tree for MutableTree

* fix Error: struct of size 48 bytes could be of size 40 bytes

* go fmt

* more linter fixes

* fix remaining linter problems

* upgrade tm-db and comment out broken bencher databases

* skip iterations for BenchmarkLevelDBLargeData bench

* attempt to fix linter

* force GC, no cache during migration, auto heap profile (#19)

* force GC, no cache during migration, auto heap profile

* resolve a potential deadlock from racing between reset and stop

* fix small lint issue

* remove logs and pprof logic

* remove unused libraries

* add comment explaining the reason for RAM optimizations

* sync access to fast node cache to avoid concurrent write fatal error (#23)

* update go.mod and go.sum to match master versions

* revert #23 (sync access to fast node cache), fix bug related to old height export (#33)

* Revert "sync access to fast node cache to avoid concurrent write fatal error (#23)"

This reverts commit 2a1daf4.

* return correct iterator in mutable tree

* fix concurrent map panic when querying and comittting concurrently

* avoid clearing fast node cache during pruning (#35)

* fix data race related to VersionExists (#36)

* fix data race related to VersionExists

* use regular lock instead of RW in mutable_tree.go

* hardcode fast node cache size to  100k

* go fmt

* restore proof_ics23.go

* fix linter

Co-authored-by: ValarDragon <dojha12@gmail.com>
Co-authored-by: jtieri <37750742+jtieri@users.noreply.github.com>
Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>
Co-authored-by: Roman Akhtariev <34196718+akhtariev@users.noreply.github.com>
Co-authored-by: Roman <34196718+r0mvn@users.noreply.github.com>
roysc pushed a commit to roysc/iavl that referenced this pull request Jul 16, 2022
* expose isUpgradeable method on mutable tree and unit test

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

Successfully merging this pull request may close these issues.

3 participants