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

[dbnode] Make index memory RSS usage flat block over block #2037

Merged
merged 4 commits into from
Nov 17, 2019
Merged

Conversation

notbdu
Copy link
Contributor

@notbdu notbdu commented Nov 6, 2019

What this PR does / why we need it:
Currently, memory usage scales w/ the size of the index up until retention. This is due to flushed index segment files being mmap'ed into memory and remaining in memory after we take a checksum. This PR naively frees file backed mmap'ed memory pages every Tick.

Special notes for your reviewer:
Left a TODO for implementing a more sophisticated free strategy in the future.

Does this PR introduce a user-facing and/or backwards incompatible change?:

- Reduce index memory usage.

Does this PR require updating code package or user-facing documentation?:
No.

@notbdu
Copy link
Contributor Author

notbdu commented Nov 7, 2019

Memory usage before on block rotations:
master

Memory usage after:
feature

@robskillington robskillington changed the title Reduce Index Memory Usage [dbnode] Make index memory RSS usage is flat block over block Nov 7, 2019
@m3db m3db deleted a comment from codecov bot Nov 7, 2019
@robskillington robskillington changed the title [dbnode] Make index memory RSS usage is flat block over block [dbnode] Make index memory RSS usage flat block over block Nov 7, 2019
@robskillington
Copy link
Collaborator

This will make tracking memory usage much easier since we don't have to rely on the kernel to evict pages under memory pressure - glad this will make operating M3DB simpler knowing how much real memory is wired!

@codecov
Copy link

codecov bot commented Nov 7, 2019

Codecov Report

Merging #2037 into master will increase coverage by 0.8%.
The diff coverage is 31.7%.

Impacted file tree graph

@@           Coverage Diff            @@
##           master   #2037     +/-   ##
========================================
+ Coverage    71.6%   72.5%   +0.8%     
========================================
  Files        1002    1009      +7     
  Lines       86381   86789    +408     
========================================
+ Hits        61919   62941   +1022     
+ Misses      20244   19622    -622     
- Partials     4218    4226      +8
Flag Coverage Δ
#aggregator 63.4% <0%> (-16.1%) ⬇️
#cluster 86.4% <ø> (+0.8%) ⬆️
#collector 74.8% <36.3%> (+61.4%) ⬆️
#dbnode 77.8% <57.1%> (-1.7%) ⬇️
#m3em 73.2% <ø> (+10.4%) ⬆️
#m3ninx 73.5% <0%> (+25%) ⬆️
#m3nsch 51.1% <ø> (+7.1%) ⬆️
#metrics 17.7% <ø> (-35.1%) ⬇️
#msg 74.7% <ø> (-0.2%) ⬇️
#query 66.3% <ø> (-2.7%) ⬇️
#x 83.5% <20%> (+18.2%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 34509a2...33c289d. Read the comment docs.


// NB(bodu): Free mmaped bytes after we take the checksum so we don't get memory spikes at bootstrap time.
if err := mmap.Free(bytes); err != nil {
closeFiles()
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: I know this is not your original code, but maybe best to use the following pattern that we do elsewhere to always call closeFiles() in case of error:

success := false
defer func() {
  if success {
    return // Returned successfully, do not need to close files
  }
  for _, file := range result.files { // This was originally closeFiles()
    file.Close()
  }
}()


// Rest of the code here

// Right before return successfully
success = true
return result, nil

Copy link
Collaborator

Choose a reason for hiding this comment

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

Then you don't need to call closeFiles() here explicitly and any new code paths automatically get the same behavior for free.

Copy link
Collaborator

@robskillington robskillington left a comment

Choose a reason for hiding this comment

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

LGTM, would love to make sure we run this w/ promremotebench with the query workload enabled for 12hrs or so (if we haven't already done that)

// of waiting for memory pressure.
// NB(bodu): DO NOT FREE anonymously mapped memory or else it will null all of the underlying bytes as the
// memory is not file backed.
func Free(b []byte) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

How do you feel about calling this DontNeed or something? Free makes me think looking through the code that the mmap should be unusable after that but thats not the case here

Copy link
Collaborator

@robskillington robskillington Nov 14, 2019

Choose a reason for hiding this comment

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

It's definitely not 100% a "Free" operation, that's true. @notbdu perhaps we calls this MadviseDontNeed(..) to match the naming of Munmap(...)?

@richardartoul
Copy link
Contributor

Does this P.R actually improve performance in any way, or is the goal to just not waste a bunch of O.S resources right after bootstrap on all these pages? Just seems a little weird to me since in theory the O.S should do an ok job of releasing these resources when they're needed. Is it to make the RSS of the m3db processes just look like its not using so much memory?

@notbdu
Copy link
Contributor Author

notbdu commented Nov 14, 2019

@richardartoul this makes for easier tracking of memory that's actually in use.

The go runtime itself also uses madvise to advise the kernel on memory pages it no longer needs.
https://golang.org/src/runtime/mem_linux.go?s=837:880#L29

@richardartoul
Copy link
Contributor

@notbdu cool was just curious

@notbdu
Copy link
Contributor Author

notbdu commented Nov 17, 2019

Ran promremotebench w/ query activated for ~36h w/ no errors.

@m3db m3db deleted a comment from codecov bot Apr 30, 2020
@m3db m3db deleted a comment from codecov bot Apr 30, 2020
@m3db m3db deleted a comment from codecov bot Apr 30, 2020
@m3db m3db deleted a comment from codecov bot Apr 30, 2020
@m3db m3db deleted a comment from codecov bot Apr 30, 2020
@m3db m3db deleted a comment from codecov bot Apr 30, 2020
@m3db m3db deleted a comment from codecov bot Apr 30, 2020
@m3db m3db deleted a comment from codecov bot Apr 30, 2020
@m3db m3db deleted a comment from codecov bot Apr 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants