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

*: fix memory leak after dom.Close #28027

Merged
merged 9 commits into from
Sep 14, 2021
Merged

Conversation

lance6716
Copy link
Contributor

What problem does this PR solve?

Issue Number: close #18048

Problem Summary: memory leak after dom.Close

What is changed and how it works?

How it Works:

  • remove store from domap when dom.Close
  • expose a way to not RegisterStatistics to global variables

Check List

Tests

  • Unit test

Side effects

Documentation

Release note

None

@ti-chi-bot
Copy link
Member

ti-chi-bot commented Sep 14, 2021

[REVIEW NOTIFICATION]

This pull request has been approved by:

  • gozssky
  • wjhuang2016

To complete the pull request process, please ask the reviewers in the list to review by filling /cc @reviewer in the comment.
After your PR has acquired the required number of LGTMs, you can assign this pull request to the committer in the list by filling /assign @committer in the comment to help you merge this pull request.

The full list of commands accepted by this bot can be found here.

Reviewer can indicate their review by submitting an approval review.
Reviewer can cancel approval by submitting a request changes review.

@ti-chi-bot ti-chi-bot added the release-note-none Denotes a PR that doesn't merit a release note. label Sep 14, 2021
@ti-chi-bot ti-chi-bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Sep 14, 2021
@lance6716
Copy link
Contributor Author

/cc @wjhuang2016 @gozssky @glorv

domain/domain.go Outdated
@@ -605,6 +605,9 @@ func (do *Domain) isClose() bool {
return false
}

// DomainMapDelete is used to avoid cycle import with `session` package.
var DomainMapDelete func (kv.Storage)
Copy link
Contributor

Choose a reason for hiding this comment

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

How about adding a `callback' to Domain instead of another global variable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

how can we pass the callback? domain package can't access session package

Copy link
Contributor

Choose a reason for hiding this comment

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

like this

type Domain struct {
	callback func()
}

Copy link
Contributor

@sleepymole sleepymole Sep 14, 2021

Choose a reason for hiding this comment

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

On the other hand, domain is created by domap.Get(), so is domap's responsibility to call domain.Close?

session/tidb.go Outdated
@@ -42,6 +42,12 @@ import (
"go.uber.org/zap"
)

func init() {
domain.DomainMapDelete = func(store kv.Storage) {
domap.Delete(store)
Copy link
Contributor

Choose a reason for hiding this comment

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

There is another global map storeBootstrapped which hold a storeUUID -> bool. ResetStoreForWithTiKVTest is a similar function to clean the two maps.

var RegisterStatistics = registerStatistics

// registerStatistics registers statistics.
func registerStatistics(s Statistics) {
Copy link
Contributor

@sleepymole sleepymole Sep 14, 2021

Choose a reason for hiding this comment

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

I think we should add a function like UnregisterStatistics and call it when domain or ddl is closed. It seems memory leak also happen in TiDB server, because BootstrapSession opens domain twice.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

there's no id for Statistics, we can't find the one we appended (maybe by memory address?)

Copy link
Contributor

Choose a reason for hiding this comment

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

Directly comparing interface?

@sleepymole
Copy link
Contributor

tidb/bindinfo/handle.go

Lines 106 to 122 in c26038b

func NewBindHandle(ctx sessionctx.Context) *BindHandle {
handle := &BindHandle{}
handle.sctx.Context = ctx
handle.bindInfo.Value.Store(make(cache, 32))
handle.bindInfo.parser = parser.New()
handle.invalidBindRecordMap.Value.Store(make(map[string]*bindRecordUpdate))
handle.invalidBindRecordMap.flushFunc = func(record *BindRecord) error {
return handle.DropBindRecord(record.OriginalSQL, record.Db, &record.Bindings[0])
}
handle.pendingVerifyBindRecordMap.Value.Store(make(map[string]*bindRecordUpdate))
handle.pendingVerifyBindRecordMap.flushFunc = func(record *BindRecord) error {
// BindSQL has already been validated when coming here, so we use nil sctx parameter.
return handle.AddBindRecord(nil, record)
}
variable.RegisterStatistics(handle)
return handle
}

BindHandle also need to unregister statistics.

@lance6716
Copy link
Contributor Author

lance6716 commented Sep 14, 2021

tidb/bindinfo/handle.go

Lines 106 to 122 in c26038b

func NewBindHandle(ctx sessionctx.Context) *BindHandle {
handle := &BindHandle{}
handle.sctx.Context = ctx
handle.bindInfo.Value.Store(make(cache, 32))
handle.bindInfo.parser = parser.New()
handle.invalidBindRecordMap.Value.Store(make(map[string]*bindRecordUpdate))
handle.invalidBindRecordMap.flushFunc = func(record *BindRecord) error {
return handle.DropBindRecord(record.OriginalSQL, record.Db, &record.Bindings[0])
}
handle.pendingVerifyBindRecordMap.Value.Store(make(map[string]*bindRecordUpdate))
handle.pendingVerifyBindRecordMap.flushFunc = func(record *BindRecord) error {
// BindSQL has already been validated when coming here, so we use nil sctx parameter.
return handle.AddBindRecord(nil, record)
}
variable.RegisterStatistics(handle)
return handle
}

BindHandle also need to unregister statistics.

its assigned to Domain and unregistered in variable.UnregisterStatistics(do.bindHandle) when Domain.Close

@sleepymole
Copy link
Contributor

tidb/bindinfo/handle.go

Lines 106 to 122 in c26038b

func NewBindHandle(ctx sessionctx.Context) *BindHandle {
handle := &BindHandle{}
handle.sctx.Context = ctx
handle.bindInfo.Value.Store(make(cache, 32))
handle.bindInfo.parser = parser.New()
handle.invalidBindRecordMap.Value.Store(make(map[string]*bindRecordUpdate))
handle.invalidBindRecordMap.flushFunc = func(record *BindRecord) error {
return handle.DropBindRecord(record.OriginalSQL, record.Db, &record.Bindings[0])
}
handle.pendingVerifyBindRecordMap.Value.Store(make(map[string]*bindRecordUpdate))
handle.pendingVerifyBindRecordMap.flushFunc = func(record *BindRecord) error {
// BindSQL has already been validated when coming here, so we use nil sctx parameter.
return handle.AddBindRecord(nil, record)
}
variable.RegisterStatistics(handle)
return handle
}

BindHandle also need to unregister statistics.

its assigned to Domain and unregistered in variable.UnregisterStatistics(do.bindHandle)

I missed it 😂

@ti-chi-bot ti-chi-bot added the status/LGT1 Indicates that a PR has LGTM 1. label Sep 14, 2021
@ti-chi-bot ti-chi-bot added status/LGT2 Indicates that a PR has LGTM 2. and removed status/LGT1 Indicates that a PR has LGTM 1. labels Sep 14, 2021
@tiancaiamao
Copy link
Contributor

[2021-09-14T05:31:45.434Z] ----------------------------------------------------------------------
[2021-09-14T05:31:45.434Z] FAIL: bootstrap_test.go:324: testBootstrapSuite.TestIssue17979_2
[2021-09-14T05:31:45.434Z] 
[2021-09-14T05:31:45.434Z] bootstrap_test.go:364:
[2021-09-14T05:31:45.434Z]     c.Assert(config.GetGlobalConfig().OOMAction, Equals, config.OOMActionCancel)
[2021-09-14T05:31:45.434Z] ... obtained string = "log"
[2021-09-14T05:31:45.434Z] ... expected string = "cancel"
[2021-09-14T05:31:45.434Z] 
[2021-09-14T05:31:46.002Z] 
[2021-09-14T05:31:46.002Z] ----------------------------------------------------------------------

@lance6716
Copy link
Contributor Author

[2021-09-14T05:31:45.434Z] ----------------------------------------------------------------------
[2021-09-14T05:31:45.434Z] FAIL: bootstrap_test.go:324: testBootstrapSuite.TestIssue17979_2
[2021-09-14T05:31:45.434Z] 
[2021-09-14T05:31:45.434Z] bootstrap_test.go:364:
[2021-09-14T05:31:45.434Z]     c.Assert(config.GetGlobalConfig().OOMAction, Equals, config.OOMActionCancel)
[2021-09-14T05:31:45.434Z] ... obtained string = "log"
[2021-09-14T05:31:45.434Z] ... expected string = "cancel"
[2021-09-14T05:31:45.434Z] 
[2021-09-14T05:31:46.002Z] 
[2021-09-14T05:31:46.002Z] ----------------------------------------------------------------------

I can't reproduce it in my local go test -check.f "...TestIssue17979_2", need your help 😂

@lance6716
Copy link
Contributor Author

/merge

@ti-chi-bot
Copy link
Member

This pull request has been accepted and is ready to merge.

Commit hash: 3e9e3c9

@ti-chi-bot ti-chi-bot added the status/can-merge Indicates a PR has been approved by a committer. label Sep 14, 2021
@ti-chi-bot
Copy link
Member

@lance6716: Your PR was out of date, I have automatically updated it for you.

At the same time I will also trigger all tests for you:

/run-all-tests

If the CI test fails, you just re-trigger the test that failed and the bot will merge the PR for you after the CI passes.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the ti-community-infra/tichi repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-note-none Denotes a PR that doesn't merit a release note. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. status/can-merge Indicates a PR has been approved by a committer. status/LGT2 Indicates that a PR has LGTM 2.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

memory leak in mockstore
5 participants