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

geth: add flag to control auto db compaction #317

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ func initGenesis(ctx *cli.Context) error {
overrides.OverrideVerkle = &v
}
for _, name := range []string{"chaindata", "lightchaindata"} {
chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false)
chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false, false)
if err != nil {
utils.Fatalf("Failed to open database: %v", err)
}
Expand Down Expand Up @@ -258,7 +258,7 @@ func dumpGenesis(ctx *cli.Context) error {
// dump whatever already exists in the datadir
stack, _ := makeConfigNode(ctx)
for _, name := range []string{"chaindata", "lightchaindata"} {
db, err := stack.OpenDatabase(name, 0, 0, "", true)
db, err := stack.OpenDatabase(name, 0, 0, "", true, false)
if err != nil {
if !os.IsNotExist(err) {
return err
Expand Down Expand Up @@ -561,7 +561,7 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
default:
return nil, nil, common.Hash{}, fmt.Errorf("invalid start argument: %x. 20 or 32 hex-encoded bytes required", startArg)
}
var conf = &state.DumpConfig{
conf := &state.DumpConfig{
SkipCode: ctx.Bool(utils.ExcludeCodeFlag.Name),
SkipStorage: ctx.Bool(utils.ExcludeStorageFlag.Name),
OnlyWithAddresses: !ctx.Bool(utils.IncludeIncompletesFlag.Name),
Expand Down
1 change: 1 addition & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ var (
utils.CacheLogSizeFlag,
utils.FDLimitFlag,
utils.CryptoKZGFlag,
utils.DBDisableAutoCompFlag,
utils.ListenPortFlag,
utils.DiscoveryPortFlag,
utils.MaxPeersFlag,
Expand Down
21 changes: 18 additions & 3 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,12 @@ var (
Category: flags.PerfCategory,
}

DBDisableAutoCompFlag = &cli.BoolFlag{
Name: "db.disable-auto-comp",
Usage: "Disables database auto-compaction (pebble only)",
Category: flags.PerfCategory,
}

// Miner settings
MiningEnabledFlag = &cli.BoolFlag{
Name: "mine",
Expand Down Expand Up @@ -1761,6 +1767,15 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
cfg.DatabaseFreezer = ctx.String(AncientFlag.Name)
}

if flag := DBDisableAutoCompFlag.Name; ctx.IsSet(flag) {
val := ctx.Bool(flag)
cfg.DisableAutomaticDBCompactions = val
if val {
log.Info("Disabling automatic database compaction")
}
// Don't log default behavior.
}

if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
}
Expand Down Expand Up @@ -1952,7 +1967,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) {
cfg.Genesis = nil // fallback to db content

//validate genesis has PoS enabled in block 0
// validate genesis has PoS enabled in block 0
genesis, err := core.ReadGenesis(chaindb)
if err != nil {
Fatalf("Could not read genesis from database: %v", err)
Expand Down Expand Up @@ -2145,9 +2160,9 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.
}
chainDb = remotedb.New(client)
case ctx.String(SyncModeFlag.Name) == "light":
chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly)
chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly, false)
default:
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly)
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly, false)
}
if err != nil {
Fatalf("Could not open database: %v", err)
Expand Down
11 changes: 7 additions & 4 deletions core/rawdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,8 @@ func NewLevelDBDatabase(file string, cache int, handles int, namespace string, r

// NewPebbleDBDatabase creates a persistent key-value database without a freezer
// moving immutable chain segments into cold storage.
func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly, ephemeral bool) (ethdb.Database, error) {
db, err := pebble.New(file, cache, handles, namespace, readonly, ephemeral)
func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly, ephemeral bool, noAutoComp bool) (ethdb.Database, error) {
db, err := pebble.New(file, cache, handles, namespace, readonly, ephemeral, noAutoComp)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -366,6 +366,9 @@ type OpenOptions struct {
// Ephemeral means that filesystem sync operations should be avoided: data integrity in the face of
// a crash is not important. This option should typically be used in tests.
Ephemeral bool

// Disable auto-compaction (PebbleDB only)
NoAutoCompaction bool
}

// openKeyValueDatabase opens a disk-based key-value database, e.g. leveldb or pebble.
Expand All @@ -387,15 +390,15 @@ func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
}
if o.Type == dbPebble || existingDb == dbPebble {
log.Info("Using pebble as the backing database")
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral)
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral, o.NoAutoCompaction)
}
if o.Type == dbLeveldb || existingDb == dbLeveldb {
log.Info("Using leveldb as the backing database")
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
}
// No pre-existing database, no user-requested one either. Default to Pebble.
log.Info("Defaulting to pebble as the backing database")
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral)
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral, o.NoAutoCompaction)
}

// Open opens both a disk-based key-value database such as leveldb or pebble, but also
Expand Down
2 changes: 1 addition & 1 deletion eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024)

// Assemble the Ethereum object
chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/", false)
chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/", false, config.DisableAutomaticDBCompactions)
if err != nil {
return nil, err
}
Expand Down
2 changes: 2 additions & 0 deletions eth/ethconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ type Config struct {
RollupDisableTxPoolGossip bool
RollupDisableTxPoolAdmission bool
RollupHaltOnIncompatibleProtocolVersion string

DisableAutomaticDBCompactions bool
}

// CreateConsensusEngine creates a consensus engine for the given chain config.
Expand Down
7 changes: 5 additions & 2 deletions ethdb/pebble/pebble.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func (l panicLogger) Fatalf(format string, args ...interface{}) {

// New returns a wrapped pebble DB object. The namespace is the prefix that the
// metrics reporting should use for surfacing internal stats.
func New(file string, cache int, handles int, namespace string, readonly bool, ephemeral bool) (*Database, error) {
func New(file string, cache int, handles int, namespace string, readonly bool, ephemeral bool, noAutoComp bool) (*Database, error) {
// Ensure we have some minimal caching and file guarantees
if cache < minCache {
cache = minCache
Expand All @@ -144,7 +144,8 @@ func New(file string, cache int, handles int, namespace string, readonly bool, e
handles = minHandles
}
logger := log.New("database", file)
logger.Info("Allocated cache and file handles", "cache", common.StorageSize(cache*1024*1024), "handles", handles)
logger.Info("Allocated cache and file handles", "cache", common.StorageSize(cache*1024*1024), "handles", handles,
"no_auto_compaction", noAutoComp)

// The max memtable size is limited by the uint32 offsets stored in
// internal/arenaskl.node, DeferredBatchOp, and flushableBatchEntry.
Expand Down Expand Up @@ -219,6 +220,8 @@ func New(file string, cache int, handles int, namespace string, readonly bool, e
WriteStallEnd: db.onWriteStallEnd,
},
Logger: panicLogger{}, // TODO(karalabe): Delete when this is upstreamed in Pebble

DisableAutomaticCompactions: noAutoComp,
}
// Disable seek compaction explicitly. Check https://github.com/ethereum/go-ethereum/pull/20130
// for more details.
Expand Down
8 changes: 6 additions & 2 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ func (n *Node) EventMux() *event.TypeMux {
// OpenDatabase opens an existing database with the given name (or creates one if no
// previous can be found) from within the node's instance directory. If the node is
// ephemeral, a memory database is returned.
func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, readonly bool) (ethdb.Database, error) {
func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, readonly bool, noAutoComp bool) (ethdb.Database, error) {
n.lock.Lock()
defer n.lock.Unlock()
if n.state == closedState {
Expand All @@ -732,6 +732,8 @@ func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, r
Cache: cache,
Handles: handles,
ReadOnly: readonly,

NoAutoCompaction: noAutoComp,
})
}

Expand All @@ -746,7 +748,7 @@ func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, r
// also attaching a chain freezer to it that moves ancient chain data from the
// database to immutable append-only files. If the node is an ephemeral one, a
// memory database is returned.
func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient string, namespace string, readonly bool) (ethdb.Database, error) {
func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient string, namespace string, readonly bool, noAutoComp bool) (ethdb.Database, error) {
n.lock.Lock()
defer n.lock.Unlock()
if n.state == closedState {
Expand All @@ -765,6 +767,8 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient
Cache: cache,
Handles: handles,
ReadOnly: readonly,

NoAutoCompaction: noAutoComp,
})
}

Expand Down
10 changes: 4 additions & 6 deletions node/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ import (
"github.com/stretchr/testify/assert"
)

var (
testNodeKey, _ = crypto.GenerateKey()
)
var testNodeKey, _ = crypto.GenerateKey()

func testNodeConfig() *Config {
return &Config{
Expand Down Expand Up @@ -152,7 +150,7 @@ func TestNodeCloseClosesDB(t *testing.T) {
stack, _ := New(testNodeConfig())
defer stack.Close()

db, err := stack.OpenDatabase("mydb", 0, 0, "", false)
db, err := stack.OpenDatabase("mydb", 0, 0, "", false, true)
if err != nil {
t.Fatal("can't open DB:", err)
}
Expand All @@ -175,7 +173,7 @@ func TestNodeOpenDatabaseFromLifecycleStart(t *testing.T) {
var err error
stack.RegisterLifecycle(&InstrumentedService{
startHook: func() {
db, err = stack.OpenDatabase("mydb", 0, 0, "", false)
db, err = stack.OpenDatabase("mydb", 0, 0, "", false, true)
if err != nil {
t.Fatal("can't open DB:", err)
}
Expand All @@ -196,7 +194,7 @@ func TestNodeOpenDatabaseFromLifecycleStop(t *testing.T) {

stack.RegisterLifecycle(&InstrumentedService{
stopHook: func() {
db, err := stack.OpenDatabase("mydb", 0, 0, "", false)
db, err := stack.OpenDatabase("mydb", 0, 0, "", false, true)
if err != nil {
t.Fatal("can't open DB:", err)
}
Expand Down