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

Memtree #11

Merged
merged 52 commits into from
Jul 2, 2019
Merged

Memtree #11

merged 52 commits into from
Jul 2, 2019

Conversation

mattkanwisher
Copy link

No description provided.

enlight and others added 30 commits February 20, 2019 11:31
This makes it possible to persist leaf node values separately from the
tree nodes themselves. As leaf nodes are loaded their values are read
from the external store, when they're persisted to disk the values are
omitted. The external value store needs to be updated separately when
a key is set or deleted in the MutableTree.
Previously there was a single mutex that had to be acquired by a
reader/writer before they could access either the node cache or the
underlying DB. These changes introduce a second mutex to synchronize
access to the node cache, while the original mutex is now only used to
synchronize write access to the underlying DB.

Multiple readers may now access the underlying DB concurrently, this
should work with GoLevelDB at least since it supports concurrent readers.
The multi-mutex NodeDB is now called NodeDB2, both the new
implementation and the old one implement the new NodeDB interface.
MutableTree & ImmutableTree have been modified to only interact with the
NodeDB interface, so they can be used with either of the two NodeDB
implementations.
Add MutableTree.SaveVersionToDB to extract a single IAVL tree version
@mattkanwisher mattkanwisher merged commit bed4822 into tmreal Jul 2, 2019
mattkanwisher added a commit that referenced this pull request Jul 2, 2019
* Memtree (#11)

Storing intermidiary IAVL versions in memory and not to disk

Motivation: Both Cosmos and Loom Network save an IAVL version per block, then go back and delete these versions. So you have constant churn on the IAVL and underlying Leveldb database. When realistically what you want is to only store every X Blocks.

At Berlin Tendermint Conference, Zaki and I surmised a plan where new versions are in memory, while still pointing back to nodes on disk to prevent needing to load entire IAVL into main memory. Loom IAVL tree is around 256gb so this is not feasible otherwise.


Usage

OLD Code would be like

```go
hash, version, err := s.tree.SaveVersion()
```

New Caller code would look like

```go
	oldVersion := s.Version()
  	var version int64
 	var hash []byte
 	//Every X versions we should persist to disk
 	if s.flushInterval == 0 || ((oldVersion+1)%s.flushInterval == 0) {
 		if s.flushInterval != 0 {
 			log.Error(fmt.Sprintf("Flushing mem to disk at version %d\n", oldVersion+1))
 			hash, version, err = s.tree.FlushMemVersionDisk()
 		} else {
 			hash, version, err = s.tree.SaveVersion()
 		}
 	} else {
 		hash, version, err = s.tree.SaveVersionMem()
 	}
```

FlushMemVersionDisk:
Flushes the current memory version to disk

SaveVersionMem:
Saves the current tree to memory instead of disk and gives you back an apphash

This is an opt in feature, you have to call new apis to get it. 
We also have a PR that demonstrates its usage https://github.com/loomnetwork/loomchain/pull/1232/files

We are now commiting every 1000 blocks, so we store 1000x less. Also we have signficant improves in IO at least double from not having to Prune old versions of the IAVL Tree

* Add version saving to in memory, and ability to flush to disk periodically
enlight pushed a commit that referenced this pull request Aug 26, 2019
Storing intermediary IAVL versions in memory and not to disk

Motivation: Both Cosmos and Loom Network save an IAVL version per block,
then go back and delete these versions. So you have constant churn on
the IAVL and underlying Leveldb database. When realistically what you
want is to only store every X Blocks.

At Berlin Tendermint Conference, Zaki and I surmised a plan where new
versions are in memory, while still pointing back to nodes on disk to
prevent needing to load entire IAVL into main memory. Loom IAVL tree is
around 256gb so this is not feasible otherwise.

Usage

OLD Code would be like

```go
hash, version, err := s.tree.SaveVersion()
```

New Caller code would look like

```go
 oldVersion := s.Version()
   var version int64
  var hash []byte
  //Every X versions we should persist to disk
  if s.flushInterval == 0 || ((oldVersion+1)%s.flushInterval == 0) {
   if s.flushInterval != 0 {
    log.Error(fmt.Sprintf("Flushing mem to disk at version %d\n", oldVersion+1))
    hash, version, err = s.tree.FlushMemVersionDisk()
   } else {
    hash, version, err = s.tree.SaveVersion()
   }
  } else {
   hash, version, err = s.tree.SaveVersionMem()
  }
```

FlushMemVersionDisk:
Flushes the current memory version to disk

SaveVersionMem:
Saves the current tree to memory instead of disk and gives you back an
apphash.

This is an opt in feature, you have to call new apis to get it.
We also have a PR that demonstrates its usage
https://github.com/loomnetwork/loomchain/pull/1232/files

We are now committing every 1000 blocks, so we store 1000x less. Also we
have significant improves in IO at least double from not having to Prune
old versions of the IAVL Tree
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