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

Dynamically resizes cache depending on the amount of RAM available (issue #167) #213

Merged
merged 42 commits into from
Jun 11, 2021

Conversation

alonlong
Copy link
Contributor

Fix the issue: Dynamically resize cache depending on the amount of RAM available #167

@alonlong alonlong added enhancement New feature or request backend Mostly go code labels May 25, 2021
@codecov
Copy link

codecov bot commented May 25, 2021

Codecov Report

Merging #213 (e114d9b) into main (c1babda) will decrease coverage by 1.31%.
The diff coverage is 44.45%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #213      +/-   ##
==========================================
- Coverage   55.65%   54.35%   -1.30%     
==========================================
  Files          82       83       +1     
  Lines        3249     3467     +218     
==========================================
+ Hits         1808     1884      +76     
- Misses       1259     1392     +133     
- Partials      182      191       +9     
Impacted Files Coverage Δ
pkg/agent/selfprofile.go 0.00% <0.00%> (ø)
pkg/agent/upstream/direct/direct.go 0.00% <0.00%> (ø)
pkg/cli/cli.go 61.25% <0.00%> (ø)
pkg/cli/server_unix.go 0.00% <0.00%> (ø)
pkg/cli/usage.go 9.76% <0.00%> (-0.50%) ⬇️
pkg/server/ingest.go 56.80% <0.00%> (-3.73%) ⬇️
pkg/storage/key.go 88.71% <ø> (-0.17%) ⬇️
pkg/storage/local.go 0.00% <0.00%> (ø)
pkg/util/atexit/atexit.go 0.00% <0.00%> (ø)
pkg/util/attime/attime.go 100.00% <ø> (ø)
... and 16 more

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 c1babda...e114d9b. Read the comment docs.

@petethepig petethepig changed the title fix the issue #167 Dynamically resizes cache depending on the amount of RAM available (issue #167) May 26, 2021
<-cache.cleanupDone
}

func (cache *Cache) Evit(percent float64) {
Copy link
Member

Choose a reason for hiding this comment

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

Is this a typo? I think you meant Evict

Copy link
Contributor Author

Choose a reason for hiding this comment

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

right~ sorry

@@ -163,6 +164,42 @@ func New(cfg *config.Config) (*Storage, error) {
return tree.New()
}

// load the total memory of the server
vm, err := mem.VirtualMemory()
Copy link
Member

Choose a reason for hiding this comment

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

Can you please add tests for this whole PR?

For tests we could add a way to set this limit arbitrarily, to something like 1 MB, and then make sure the system still works.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

already add the test for this PR

pkg/storage/cache/cache.go Outdated Show resolved Hide resolved
// start a timer for checking if the memory used by application
// is more than 25% of the total memory, if so, trigger eviction
// with 10% to every cache
go func() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps it would be better to have this as a separate function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good idea

// is more than 25% of the total memory, if so, trigger eviction
// with 10% to every cache
go func() {
ticker := time.NewTimer(interval * time.Second)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think a Ticker is more appropriate here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

why?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Timers are for when you want to do something once in the future - tickers are for when you want to do something repeatedly at regular intervals.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, but i reset the timer in the loop

// reset the timer
ticker.Reset(interval * time.Second)

Copy link
Collaborator

Choose a reason for hiding this comment

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

For sure that works. However, I think it would be better to use more idiomatic approach with Ticker :)

Copy link
Member

Choose a reason for hiding this comment

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

@kolesnikovae I talked with @alonlong about it. I think the idea is that if this procedure takes longer than the timer we want to wait for another X seconds (10 right now I think) before flushing.

So I think it's fine. Although, I wonder if we should just add a time.Sleep there. What do you both think about that? I think that would make code more concise, but maybe there're some downsides I'm not thinking of.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ticker also has Reset method for that.

Sorry guys if led you astray. Please don't get me wrong, I was just trying to say that Timer and Ticker have different semantics, and for this particular case the last one is more appropriate IMO. Taking into account the mismatch of the variable name and the type it's a bit confusing: is it supposed to be a timer and the variable name should be changed, or is it a ticker indeed and the type should be changed? Both options are okay.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kolesnikovae Got it, I think we can change variable name to timer

defer ticker.Stop()

for range ticker.C {
if s.closing {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess this will cause races.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

can u help to describe the races?

Copy link
Collaborator

Choose a reason for hiding this comment

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

There is a race condition on access to closing field, you should acquire closingMutex and release it only after Evict calls. See Close: basically, I think that we could replace the mutex with an RWMutex.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

for range ticker.C {
if s.closing {
return
}

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 is no closingMutex here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

actually, i think for the field closing, the mutex is not necessary. the code is weird for using the mutex for closing

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm afraid, without a mutex, there is no other way to avoid the race (without changing too many things): eventually the call will conflict with Close.

closingMutex is a member of Storage:
https://github.com/pyroscope-io/pyroscope/blob/f45b14e491357af26f8a32e989ef573d1b86e8d3/pkg/storage/storage.go#L38-L40

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's a bool variable, i think it's not a problem

Copy link
Collaborator

Choose a reason for hiding this comment

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

Regardless of the type, when the same address accessed for read-write concurrently, a race condition occurs. The funny part is that it would be safer to not check closing field at all in this particular function, because Evict and Flush (in Close) methods can be called in arbitrary order with no issues :)

@petethepig petethepig merged commit 764de1d into main Jun 11, 2021
@petethepig petethepig deleted the feature/resize_cache branch June 11, 2021 05:44
korniltsev pushed a commit that referenced this pull request Jul 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend Mostly go code enhancement New feature or request
Projects
Development

Successfully merging this pull request may close these issues.

None yet

4 participants