-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
executor: fix the issue that pb
memory cannot be released quickly
#10815
Conversation
Codecov Report
@@ Coverage Diff @@
## master #10815 +/- ##
================================================
+ Coverage 80.2889% 80.2964% +0.0074%
================================================
Files 417 417
Lines 88453 88456 +3
================================================
+ Hits 71018 71027 +9
+ Misses 12231 12221 -10
- Partials 5204 5208 +4 |
Codecov Report
@@ Coverage Diff @@
## master #10815 +/- ##
===============================================
+ Coverage 80.829% 80.8502% +0.0211%
===============================================
Files 419 417 -2
Lines 88608 88262 -346
===============================================
- Hits 71621 71360 -261
+ Misses 11759 11693 -66
+ Partials 5228 5209 -19 |
There are many unit tests running parallelly, so they may influence each other to let this unit test unstable. |
/run-all-tests |
emm..parallel running is a problem... maybe we can make an the idea is that after running just fetch a heap profile, using then just loop then if we can find any MemProfileRecord that:
|
....but this case held memory is alloc in another goroutine...stack isn't start with TestDistSqlLeak 🤣 |
After discussing with @XuHuaiyu and reviewing |
2837656
to
4b356bf
Compare
/run-all-tests |
// prepare data | ||
totalSize := uint64(256 << 20) // 256MB | ||
blockSize := uint64(8 << 10) // 8KB | ||
delta := totalSize / 5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just an empirical value, used to judge if memory leak happens.
The difference between InUseHeap
before and after a query must be less than it.
executor/memory_test.go
Outdated
} | ||
d, err := session.BootstrapSession(s.store) | ||
c.Assert(err, IsNil) | ||
d.SetStatsUpdating(true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to perform?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The unnecessary code in testMemoryLeak
has been removed now.
se.Close() | ||
runtime.GC() | ||
allocatedFinal, inUseFinal := s.readMem() | ||
c.Assert(allocatedFinal-allocatedAfter, Less, delta) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we check allocatedFinal-allocatedAfter
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To ensure that these executors don't allocate much memory when closing.
runtime.GC() | ||
allocatedAfter, inUseAfter := s.readMem() | ||
c.Assert(allocatedAfter-allocatedBegin, GreaterEqual, totalSize) | ||
c.Assert(s.memDiff(inUseAfter, inUseBegin), Less, delta) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to check s.memDiff(inUseAfter, inUseBegin)
before line 86?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check ensures that the memory used in this query can be recycled by the GC scanner.
If we put this check before line 86, since we don't know if GC happens when processing this query, the value of s.memDiff(inUseAfter, inUseBegin)
would be indeterminate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
What problem does this PR solve?
Fix the issue that
pb
memory cannot be released quickly.What is changed and how it works?
In this PR(stmtctx.go:296), we let
sc
holddetail
until the query finish to get more coptask's execution information.Because
detail
is nested incopResponse
, if we hold its pointer, the Golang GC scanner will regardcopResponse
as active, and will not release until the query finish.Then another field
pbResp
held bycopResonse
will not be released quickly.Since
pbResp
is used to bufferpb
data, it results in more memory consumption.Check List
Tests