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

multi: Add UtxoCache. #2591

Merged
merged 10 commits into from
Feb 22, 2021
Merged

multi: Add UtxoCache. #2591

merged 10 commits into from
Feb 22, 2021

Commits on Feb 19, 2021

  1. Configuration menu
    Copy the full SHA
    896c159 View commit details
    Browse the repository at this point in the history
  2. blockchain: Separate utxo state from tx flags.

    This splits the utxo packed flags into two separate types, utxoState
    and utxoFlags.  The reasoning is that:
    - This cleanly separates the purpose of the flags.  utxoState defines
      the in-memory state of a utxo entry, whereas utxoFlags defines
      additional information for the containing transaction of a utxo
      entry.
    - This makes room for an additional state that is required for the utxo
      cache, namely whether or not a utxo entry is fresh (does not exist as
      an unspent transaction output in the database).
    rstaudt2 committed Feb 19, 2021
    Configuration menu
    Copy the full SHA
    e55207b View commit details
    Browse the repository at this point in the history
  3. blockchain: Add utxoStateFresh to UtxoEntry.

    This adds utxoStateFresh to UtxoEntry to indicate that a txout is fresh,
    which means that it exists in the utxo cache but does not exist in the
    underlying database.
    
    The utxo cache will use the fresh flag as an optimization to skip
    writing to the database for outputs that are added and spent in between
    flushes to the database.
    rstaudt2 committed Feb 19, 2021
    Configuration menu
    Copy the full SHA
    e23c565 View commit details
    Browse the repository at this point in the history
  4. blockchain: Add size method to UtxoEntry.

    This adds a size method to UtxoEntry, which returns the number of bytes
    that the entry uses on a 64-bit platform.  This will be used as part of
    tracking the total size of the utxo cache.
    rstaudt2 committed Feb 19, 2021
    Configuration menu
    Copy the full SHA
    c5d7003 View commit details
    Browse the repository at this point in the history
  5. config: Add utxocachemaxsize.

    This adds a utxocachemaxsize configuration option which represents the
    maximum size in MiB of the utxo cache.  The default value is 150 MiB,
    the minimum value is 25 MiB, and the maximum value is 32768 MiB
    (32 GiB).
    rstaudt2 committed Feb 19, 2021
    Configuration menu
    Copy the full SHA
    4b42840 View commit details
    Browse the repository at this point in the history
  6. blockchain: Deep copy view entry script from tx.

    This updates utxo viewpoints to deep copy the script when getting it
    from a msg tx.  This is required since the tx out script is a subslice
    of the overall contiguous buffer that the msg tx houses for all scripts
    within the tx.  It is deep copied here since this entry may be added to
    the utxo cache, and we don't want the utxo cache holding the entry to
    prevent all of the other tx scripts from getting garbage collected.
    rstaudt2 committed Feb 19, 2021
    Configuration menu
    Copy the full SHA
    8de043c View commit details
    Browse the repository at this point in the history
  7. blockchain: Add utxoSetState to the database.

    This adds a utxoSetState type that is tracked in the database. The utxo
    set state contains information regarding the current state of the utxo
    set.  In particular, it tracks the block height and block hash of the
    last completed flush.
    
    The utxo set state is tracked in the database since at any given time,
    the utxo cache may not be consistent with the utxo set in the database.
    This is due to the fact that the utxo cache only flushes changes to the
    database periodically.  Therefore, during initialization, the utxo set
    state is used to identify the last flushed state of the utxo set and it
    can be caught up to the current best state of the main chain.
    
    This additionally adds full test coverage to the new serialization and
    deserialization functions.
    rstaudt2 committed Feb 19, 2021
    Configuration menu
    Copy the full SHA
    d0814b1 View commit details
    Browse the repository at this point in the history
  8. multi: Add UtxoCache.

    UtxoCache is an unspent transaction output cache that sits on top of the
    utxo set database and provides significant runtime performance benefits
    at the cost of some additional memory usage.  It drastically reduces the
    amount of reading and writing to disk, especially during initial block
    download when a very large number of blocks are being processed in quick
    succession.
    
    The UtxoCache is a read-through cache.  All utxo reads go through the
    cache.  When there is a cache miss, the cache loads the missing data
    from the database, caches it, and returns it to the caller.
    
    The UtxoCache is a write-back cache.  Writes to the cache are
    acknowledged by the cache immediately but are only periodically flushed
    to the database.  This allows intermediate steps to effectively be
    skipped.  For example, a utxo that is created and then spent in between
    flushes never needs to be written to the utxo set in the database.
    
    Due to the write-back nature of the cache, at any given time the
    database may not be in sync with the cache, and therefore all utxo reads
    and writes MUST go through the cache, and never read or write to the
    database directly.
    
    An overview of the changes is as follows:
    
    - Add UtxoCache and UtxoCacheConfig struct types and NewUtxoCache method
      - Update server to create the utxo cache with the configured max size
        and pass to the block chain instance that is created
      - Update all test block chains to create a utxo cache
    - Add FetchEntry to UtxoCache
      - FetchEntry returns the specified transaction output from the utxo
        set
      - If the output exists in the cache, it is returned immediately.
        Otherwise, it uses an existing database transaction to fetch the
        output from the database, caches it, and returns it to the caller.
    - Add AddEntry to UtxoCache
      - AddEntry adds the specified output to the cache
    - Add SpendEntry to UtxoCache
      - SpendEntry marks the specified output as spent
      - Remove entries that are marked as fresh and then subsequently spent.
        This is an optimization to skip writing to the database for outputs
        that are added and spent in between flushes to the database.
    - Update UtxoViewpoint to hold the UtxoCache
      - Update fetching entries from the database to fetch entries from the
        cache instead
    - Add Commit to UtxoCache
      - Commit updates all entries in the cache based on the state of each
        entry in the provided view
      - All entries in the provided view that are marked as modified and
        spent are removed from the view
      - Additionally, all entries that are added to the cache are removed
        from the provided view
    - Add MaybeFlush to UtxoCache
      - MaybeFlush conditionally flushes the cache to the database
      - If the maximum size of the cache has been reached, or if the
        periodic flush duration has been reached, then a flush is required
      - A flush can be forced by setting the force flush parameter
      - Flushing commits all modified entries to the database and
        conditionally evicts entries
      - Entries that are nil or spent are always evicted since they are
        unlikely to be accessed again.  Additionally, if the cache has
        reached its maximum size, entries are evicted based on the height of
        the block that they are contained in.
    - Update connect block and disconnect block to commit to the cache and
      conditionally flush to the database
      - Rather than writing to the utxo set in the database every time that
        a block is connected or disconnected, commit the updated view to the
        cache and call MaybeFlush on the cache to conditionally flush it to
        the database
    - Add InitUtxoCache to UtxoCache
      - InitUtxoCache initializes the utxo cache by ensuring that the utxo
        set is caught up to the tip of the best chain
      - Since the cache is only flushed to the database periodically, the
        utxo set may not be caught up to the tip of the best chain
      - InitUtxoCache catches the utxo set up by replaying all blocks from
        the block after the block that was last flushed to the tip block
        through the cache
    - Add ShutdownUtxoCache to BlockChain
      - ShutdownUtxoCache flushes the utxo cache to the database on
        shutdown.  Since the cache is flushed periodically during initial
        block download and flushed after every block is connected after
        initial block download is complete, this flush that occurs during
        shutdown should finish relatively quickly
      - Note that if an unclean shutdown occurs, the cache will still be
        initialized properly when restarted as during initialization it will
        replay blocks to catch up to the tip block if it was not fully
        flushed before shutting down.  However, it is still preferred to
        flush when shutting down versus always recovering on startup since
        it is faster
    - Track the hit ratio of UtxoCache
      - Track the number of hits and misses when accessing the cache in
        order to calculate the overall hit ratio of the cache to gauge its
        performance
    rstaudt2 committed Feb 19, 2021
    Configuration menu
    Copy the full SHA
    d12d168 View commit details
    Browse the repository at this point in the history
  9. blockchain: Add UtxoCache test coverage.

    This adds full test coverage to the UtxoCache type and its methods.
    
    Additionally, since this uses the testing Cleanup function that was
    introduced in Go 1.14, this bumps the required go version for the
    blockchain package from 1.13 to 1.14.
    rstaudt2 committed Feb 19, 2021
    Configuration menu
    Copy the full SHA
    3afb445 View commit details
    Browse the repository at this point in the history
  10. docs: Update min recommended specs in README.md.

    This updates the minimum recommended memory (RAM) from 1GB to 2GB in the
    main README.md.  The minimum recommended memory is being increased due
    to the introduction of the utxo cache.
    rstaudt2 committed Feb 19, 2021
    Configuration menu
    Copy the full SHA
    e4d6623 View commit details
    Browse the repository at this point in the history