core/state, tests: fix memory leak via fastcache (#28387)

This change fixes a memory leak, when running either state-tests or blockchain-tests, we allocate a `1MB` fastcache during snapshot generation. `fastcache` is a bit special, and requires a `Reset()` (it has it's own memory allocator). 

The `1MB` was hidden [here](https://github.com/ethereum/go-ethereum/blob/master/tests/state_test_util.go#L333) and [here](https://github.com/ethereum/go-ethereum/blob/master/tests/block_test_util.go#L146) respectively.
This commit is contained in:
Martin Holst Swende 2023-10-20 13:35:49 +02:00 committed by GitHub
parent cd29535672
commit c1d5a012ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 26 additions and 1 deletions

@ -54,4 +54,4 @@ for:
- go run build/ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds - go run build/ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
- go run build/ci.go nsis -arch %GETH_ARCH% -signer WINDOWS_SIGNING_KEY -upload gethstore/builds - go run build/ci.go nsis -arch %GETH_ARCH% -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
test_script: test_script:
- go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% - go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% -short

@ -285,6 +285,7 @@ func doTest(cmdline []string) {
coverage = flag.Bool("coverage", false, "Whether to record code coverage") coverage = flag.Bool("coverage", false, "Whether to record code coverage")
verbose = flag.Bool("v", false, "Whether to log verbosely") verbose = flag.Bool("v", false, "Whether to log verbosely")
race = flag.Bool("race", false, "Execute the race detector") race = flag.Bool("race", false, "Execute the race detector")
short = flag.Bool("short", false, "Pass the 'short'-flag to go test")
cachedir = flag.String("cachedir", "./build/cache", "directory for caching downloads") cachedir = flag.String("cachedir", "./build/cache", "directory for caching downloads")
) )
flag.CommandLine.Parse(cmdline) flag.CommandLine.Parse(cmdline)
@ -318,6 +319,9 @@ func doTest(cmdline []string) {
if *race { if *race {
gotest.Args = append(gotest.Args, "-race") gotest.Args = append(gotest.Args, "-race")
} }
if *short {
gotest.Args = append(gotest.Args, "-short")
}
packages := []string{"./..."} packages := []string{"./..."}
if len(flag.CommandLine.Args()) > 0 { if len(flag.CommandLine.Args()) > 0 {

@ -989,6 +989,7 @@ func (bc *BlockChain) Stop() {
if snapBase, err = bc.snaps.Journal(bc.CurrentBlock().Root); err != nil { if snapBase, err = bc.snaps.Journal(bc.CurrentBlock().Root); err != nil {
log.Error("Failed to journal state snapshot", "err", err) log.Error("Failed to journal state snapshot", "err", err)
} }
bc.snaps.Release()
} }
if bc.triedb.Scheme() == rawdb.PathScheme { if bc.triedb.Scheme() == rawdb.PathScheme {
// Ensure that the in-memory trie nodes are journaled to disk properly. // Ensure that the in-memory trie nodes are journaled to disk properly.

@ -45,6 +45,16 @@ type diskLayer struct {
lock sync.RWMutex lock sync.RWMutex
} }
// Release releases underlying resources; specifically the fastcache requires
// Reset() in order to not leak memory.
// OBS: It does not invoke Close on the diskdb
func (dl *diskLayer) Release() error {
if dl.cache != nil {
dl.cache.Reset()
}
return nil
}
// Root returns root hash for which this snapshot was made. // Root returns root hash for which this snapshot was made.
func (dl *diskLayer) Root() common.Hash { func (dl *diskLayer) Root() common.Hash {
return dl.root return dl.root

@ -656,6 +656,13 @@ func diffToDisk(bottom *diffLayer) *diskLayer {
return res return res
} }
// Release releases resources
func (t *Tree) Release() {
if dl := t.disklayer(); dl != nil {
dl.Release()
}
}
// Journal commits an entire diff hierarchy to disk into a single journal entry. // Journal commits an entire diff hierarchy to disk into a single journal entry.
// This is meant to be used during shutdown to persist the snapshot without // This is meant to be used during shutdown to persist the snapshot without
// flattening everything down (bad for reorgs). // flattening everything down (bad for reorgs).

@ -200,6 +200,9 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bo
if triedb != nil { if triedb != nil {
triedb.Close() triedb.Close()
} }
if snaps != nil {
snaps.Release()
}
}() }()
checkedErr := t.checkError(subtest, err) checkedErr := t.checkError(subtest, err)
if checkedErr != nil { if checkedErr != nil {